made a special case for typing with BR as the selection (as after an InsertBreak.)
made DEL and BACKSPACE at the beginning and end of a text node
fixes bugs 3742 and 3756 (with permission from choff and gkostello)
This commit is contained in:
buster%netscape.com 1999-03-16 16:38:09 +00:00
Родитель 8db3d855d8
Коммит 5e09828b42
9 изменённых файлов: 319 добавлений и 100 удалений

Просмотреть файл

@ -29,8 +29,8 @@ JoinElementTxn::JoinElementTxn()
}
NS_IMETHODIMP JoinElementTxn::Init(nsIEditor *aEditor,
nsIDOMNode *aLeftNode,
nsIDOMNode *aRightNode)
nsIDOMNode *aLeftNode,
nsIDOMNode *aRightNode)
{
mEditor = do_QueryInterface(aEditor);
mLeftNode = do_QueryInterface(aLeftNode);
@ -59,21 +59,18 @@ NS_IMETHODIMP JoinElementTxn::Do(void)
{
if (leftParent==rightParent)
{
mParent=leftParent; // set this instance mParent.
// Other methods see a non-null mParent and know all is well
mParent= do_QueryInterface(leftParent); // set this instance mParent.
// Other methods will see a non-null mParent and know all is well
nsCOMPtr<nsIDOMNodeList> childNodes;
result = mLeftNode->GetChildNodes(getter_AddRefs(childNodes));
if ((NS_SUCCEEDED(result)) && (childNodes))
{
if ((NS_SUCCEEDED(result)) && (childNodes)) {
childNodes->GetLength(&mOffset);
}
//XXX: WRONG! needs commented code below
/*
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
if (NS_SUCCEEDED(result) && editor) {
result = editor->JoinNodesImpl(mLeftNode, mRightNode, mParent, PR_FALSE);
*/
result = mEditor->JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE);
nsCOMPtr<nsIEditorSupport> editor;
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
if (NS_SUCCEEDED(result) && editor) {
result = editor->JoinNodesImpl(mLeftNode, mRightNode, mParent, PR_TRUE);
}
}
}
}
@ -98,7 +95,15 @@ NS_IMETHODIMP JoinElementTxn::Undo(void)
NS_IMETHODIMP JoinElementTxn::Redo(void)
{
nsresult result = mEditor->JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE);
nsresult result;
nsCOMPtr<nsIEditorSupport> editor;
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
if (NS_SUCCEEDED(result) && editor) {
result = editor->JoinNodesImpl(mLeftNode, mRightNode, mParent, PR_TRUE);
}
else {
result = NS_ERROR_NOT_IMPLEMENTED;
}
return result;
}

Просмотреть файл

@ -119,6 +119,8 @@ static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
#endif
#define NS_ERROR_EDITOR_NO_SELECTION NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,1)
#define NS_ERROR_EDITOR_NO_TEXTNODE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,2)
/* ----- TEST METHODS DECLARATIONS ----- */
@ -876,9 +878,9 @@ NS_IMETHODIMP nsEditor::CreateNode(const nsString& aTag,
}
NS_IMETHODIMP nsEditor::CreateTxnForCreateElement(const nsString& aTag,
nsIDOMNode *aParent,
PRInt32 aPosition,
CreateElementTxn ** aTxn)
nsIDOMNode *aParent,
PRInt32 aPosition,
CreateElementTxn ** aTxn)
{
nsresult result = NS_ERROR_NULL_POINTER;
if (nsnull != aParent)
@ -904,9 +906,9 @@ NS_IMETHODIMP nsEditor::InsertNode(nsIDOMNode * aNode,
}
NS_IMETHODIMP nsEditor::CreateTxnForInsertElement(nsIDOMNode * aNode,
nsIDOMNode * aParent,
PRInt32 aPosition,
InsertElementTxn ** aTxn)
nsIDOMNode * aParent,
PRInt32 aPosition,
InsertElementTxn ** aTxn)
{
nsresult result = NS_ERROR_NULL_POINTER;
if (aNode && aParent && aTxn)
@ -997,6 +999,38 @@ nsEditor::InsertText(const nsString& aStringToInsert)
else if (NS_ERROR_EDITOR_NO_SELECTION==result) {
result = DoInitialInsert(aStringToInsert);
}
else if (NS_ERROR_EDITOR_NO_TEXTNODE==result)
{
BeginTransaction();
nsCOMPtr<nsIDOMSelection> selection;
result = GetSelection(getter_AddRefs(selection));
if ((NS_SUCCEEDED(result)) && selection)
{
nsCOMPtr<nsIDOMNode> selectedNode;
PRInt32 offset;
result = selection->GetAnchorNodeAndOffset(getter_AddRefs(selectedNode), &offset);
if ((NS_SUCCEEDED(result)) && selectedNode)
{
nsCOMPtr<nsIDOMNode> newNode;
result = CreateNode(GetTextNodeTag(), selectedNode, offset+1,
getter_AddRefs(newNode));
if (NS_SUCCEEDED(result) && newNode)
{
nsCOMPtr<nsIDOMCharacterData>newTextNode;
newTextNode = do_QueryInterface(newNode);
if (newTextNode)
{
nsAutoString placeholderText(" ");
newTextNode->SetData(placeholderText);
selection->Collapse(newNode, 0);
selection->Extend(newNode, 1);
result = InsertText(aStringToInsert);
}
}
}
}
EndTransaction();
}
return result;
}
@ -1039,6 +1073,9 @@ NS_IMETHODIMP nsEditor::CreateTxnForInsertText(const nsString & aStringToInsert,
result = NS_ERROR_UNEXPECTED;
nodeAsText = do_QueryInterface(node,&result);
range->GetStartOffset(&offset);
if (!nodeAsText) {
result = NS_ERROR_EDITOR_NO_TEXTNODE;
}
}
}
}
@ -1292,7 +1329,7 @@ nsEditor::DeleteSelection(nsIEditor::Direction aDir)
}
NS_IMETHODIMP nsEditor::CreateTxnForDeleteSelection(nsIEditor::Direction aDir,
EditAggregateTxn ** aTxn)
EditAggregateTxn ** aTxn)
{
if (!aTxn)
return NS_ERROR_NULL_POINTER;
@ -1374,7 +1411,8 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
// determine if the insertion point is at the beginning, middle, or end of the node
nsCOMPtr<nsIDOMCharacterData> nodeAsText;
nodeAsText = do_QueryInterface(node, &result);
nsCOMPtr<nsIDOMNode> selectedNode;
nodeAsText = do_QueryInterface(node);
if (nodeAsText)
{
@ -1384,18 +1422,18 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
isLast = PRBool(count==(PRUint32)offset);
}
else
{
nsCOMPtr<nsIDOMNode> sibling;
result = node->GetPreviousSibling(getter_AddRefs(sibling));
if ((NS_SUCCEEDED(result)) && sibling)
isFirst = PR_FALSE;
else
isFirst = PR_TRUE;
result = node->GetNextSibling(getter_AddRefs(sibling));
if ((NS_SUCCEEDED(result)) && sibling)
isLast = PR_FALSE;
else
isLast = PR_TRUE;
{
// get the child list and count
nsCOMPtr<nsIDOMNodeList>childList;
PRUint32 count=0;
result = node->GetChildNodes(getter_AddRefs(childList));
if ((NS_SUCCEEDED(result)) && childList)
{
childList->GetLength(&count);
childList->Item(offset, getter_AddRefs(selectedNode));
}
isFirst = PRBool(0==offset);
isLast = PRBool((count-1)==(PRUint32)offset);
}
// XXX: if isFirst && isLast, then we'll need to delete the node
// as well as the 1 child
@ -1491,6 +1529,11 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
}
else
{ // we're deleting a node
DeleteElementTxn *txn;
result = CreateTxnForDeleteElement(selectedNode, &txn);
if (NS_SUCCEEDED(result)) {
aTxn->AppendChild(txn);
}
}
}
return result;
@ -1634,13 +1677,12 @@ NS_IMETHODIMP nsEditor::CreateTxnForSplitNode(nsIDOMNode *aNode,
}
NS_IMETHODIMP
nsEditor::JoinNodes(nsIDOMNode * aNodeToKeep,
nsIDOMNode * aNodeToJoin,
nsIDOMNode * aParent,
PRBool aNodeToKeepIsFirst)
nsEditor::JoinNodes(nsIDOMNode * aLeftNode,
nsIDOMNode * aRightNode,
nsIDOMNode * aParent)
{
JoinElementTxn *txn;
nsresult result = CreateTxnForJoinNode(aNodeToKeep, aNodeToJoin, &txn);
nsresult result = CreateTxnForJoinNode(aLeftNode, aRightNode, &txn);
if (NS_SUCCEEDED(result)) {
result = Do(txn);
}
@ -1648,8 +1690,8 @@ nsEditor::JoinNodes(nsIDOMNode * aNodeToKeep,
}
NS_IMETHODIMP nsEditor::CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
nsIDOMNode *aRightNode,
JoinElementTxn **aTxn)
nsIDOMNode *aRightNode,
JoinElementTxn **aTxn)
{
nsresult result=NS_ERROR_NULL_POINTER;
if ((nsnull != aLeftNode) && (nsnull != aRightNode))

Просмотреть файл

@ -126,10 +126,9 @@ public:
PRInt32 aOffset,
nsIDOMNode ** aNewLeftNode);
NS_IMETHOD JoinNodes(nsIDOMNode * aNodeToKeep,
nsIDOMNode * aNodeToJoin,
nsIDOMNode * aParent,
PRBool aNodeToKeepIsFirst);
NS_IMETHOD JoinNodes(nsIDOMNode * aLeftNode,
nsIDOMNode * aRightNode,
nsIDOMNode * aParent);
NS_IMETHOD InsertBreak();

Просмотреть файл

@ -160,7 +160,8 @@ nsTextEditRules::WillInsertText(nsIDOMSelection *aSelection,
(*aTxn)->SetName(InsertTextTxn::gInsertTextTxnName);
mEditor->Do(*aTxn);
}
return WillInsert(aSelection, aCancel);
nsresult result = WillInsert(aSelection, aCancel);
return result;
}
NS_IMETHODIMP
@ -307,6 +308,7 @@ nsTextEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCance
}
// if the document is empty, insert a bogus text node with a &nbsp;
// if we ended up with consecutive text nodes, merge them
NS_IMETHODIMP
nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResult)
{
@ -317,7 +319,7 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul
NS_ASSERTION(PR_TRUE==isCollapsed, "selection not collapsed after delete selection.");
// if the delete selection resulted in no content
// insert a special bogus text node with a &nbsp; character in it.
if (NS_SUCCEEDED(aResult)) // note we're checking aResult, the param that tells us if the insert break happened or not
if (NS_SUCCEEDED(result)) // only do this work if DeleteSelection completed successfully
{
nsCOMPtr<nsIDOMDocument>doc;
mEditor->GetDocument(getter_AddRefs(doc));
@ -384,6 +386,68 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul
}
}
}
// if we don't have an empty document, check the selection to see if any collapsing is necessary
if (!mBogusNode)
{
nsCOMPtr<nsIDOMNode>anchor;
PRInt32 offset;
nsresult result = aSelection->GetAnchorNodeAndOffset(getter_AddRefs(anchor), &offset);
if ((NS_SUCCEEDED(result)) && anchor)
{
nsCOMPtr<nsIDOMNodeList> anchorChildren;
result = anchor->GetChildNodes(getter_AddRefs(anchorChildren));
nsCOMPtr<nsIDOMNode> selectedNode;
if ((NS_SUCCEEDED(result)) && anchorChildren) {
result = anchorChildren->Item(offset, getter_AddRefs(selectedNode));
}
else {
selectedNode = do_QueryInterface(anchor);
}
if ((NS_SUCCEEDED(result)) && selectedNode)
{
nsCOMPtr<nsIDOMCharacterData>selectedNodeAsText;
selectedNodeAsText = do_QueryInterface(selectedNode);
if (selectedNodeAsText)
{
nsCOMPtr<nsIDOMNode> siblingNode;
selectedNode->GetPreviousSibling(getter_AddRefs(siblingNode));
if (siblingNode)
{
nsCOMPtr<nsIDOMCharacterData>siblingNodeAsText;
siblingNodeAsText = do_QueryInterface(siblingNode);
if (siblingNodeAsText)
{
PRUint32 siblingLength; // the length of siblingNode before the join
siblingNodeAsText->GetLength(&siblingLength);
nsCOMPtr<nsIDOMNode> parentNode;
selectedNode->GetParentNode(getter_AddRefs(parentNode));
result = mEditor->JoinNodes(siblingNode, selectedNode, parentNode);
// set selection to point between the end of siblingNode and start of selectedNode
aSelection->Collapse(siblingNode, siblingLength);
selectedNode = do_QueryInterface(siblingNode); // subsequent code relies on selectedNode
// being the real node in the DOM tree
}
}
selectedNode->GetNextSibling(getter_AddRefs(siblingNode));
if (siblingNode)
{
nsCOMPtr<nsIDOMCharacterData>siblingNodeAsText;
siblingNodeAsText = do_QueryInterface(siblingNode);
if (siblingNodeAsText)
{
PRUint32 selectedNodeLength; // the length of siblingNode before the join
selectedNodeAsText->GetLength(&selectedNodeLength);
nsCOMPtr<nsIDOMNode> parentNode;
selectedNode->GetParentNode(getter_AddRefs(parentNode));
result = mEditor->JoinNodes(selectedNode, siblingNode, parentNode);
// set selection
aSelection->Collapse(selectedNode, selectedNodeLength);
}
}
}
}
}
}
}
return result;
}

Просмотреть файл

@ -29,8 +29,8 @@ JoinElementTxn::JoinElementTxn()
}
NS_IMETHODIMP JoinElementTxn::Init(nsIEditor *aEditor,
nsIDOMNode *aLeftNode,
nsIDOMNode *aRightNode)
nsIDOMNode *aLeftNode,
nsIDOMNode *aRightNode)
{
mEditor = do_QueryInterface(aEditor);
mLeftNode = do_QueryInterface(aLeftNode);
@ -59,21 +59,18 @@ NS_IMETHODIMP JoinElementTxn::Do(void)
{
if (leftParent==rightParent)
{
mParent=leftParent; // set this instance mParent.
// Other methods see a non-null mParent and know all is well
mParent= do_QueryInterface(leftParent); // set this instance mParent.
// Other methods will see a non-null mParent and know all is well
nsCOMPtr<nsIDOMNodeList> childNodes;
result = mLeftNode->GetChildNodes(getter_AddRefs(childNodes));
if ((NS_SUCCEEDED(result)) && (childNodes))
{
if ((NS_SUCCEEDED(result)) && (childNodes)) {
childNodes->GetLength(&mOffset);
}
//XXX: WRONG! needs commented code below
/*
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
if (NS_SUCCEEDED(result) && editor) {
result = editor->JoinNodesImpl(mLeftNode, mRightNode, mParent, PR_FALSE);
*/
result = mEditor->JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE);
nsCOMPtr<nsIEditorSupport> editor;
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
if (NS_SUCCEEDED(result) && editor) {
result = editor->JoinNodesImpl(mLeftNode, mRightNode, mParent, PR_TRUE);
}
}
}
}
@ -98,7 +95,15 @@ NS_IMETHODIMP JoinElementTxn::Undo(void)
NS_IMETHODIMP JoinElementTxn::Redo(void)
{
nsresult result = mEditor->JoinNodes(mLeftNode, mRightNode, mParent, PR_FALSE);
nsresult result;
nsCOMPtr<nsIEditorSupport> editor;
result = mEditor->QueryInterface(kIEditorSupportIID, getter_AddRefs(editor));
if (NS_SUCCEEDED(result) && editor) {
result = editor->JoinNodesImpl(mLeftNode, mRightNode, mParent, PR_TRUE);
}
else {
result = NS_ERROR_NOT_IMPLEMENTED;
}
return result;
}

Просмотреть файл

@ -119,6 +119,8 @@ static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
#endif
#define NS_ERROR_EDITOR_NO_SELECTION NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,1)
#define NS_ERROR_EDITOR_NO_TEXTNODE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,2)
/* ----- TEST METHODS DECLARATIONS ----- */
@ -876,9 +878,9 @@ NS_IMETHODIMP nsEditor::CreateNode(const nsString& aTag,
}
NS_IMETHODIMP nsEditor::CreateTxnForCreateElement(const nsString& aTag,
nsIDOMNode *aParent,
PRInt32 aPosition,
CreateElementTxn ** aTxn)
nsIDOMNode *aParent,
PRInt32 aPosition,
CreateElementTxn ** aTxn)
{
nsresult result = NS_ERROR_NULL_POINTER;
if (nsnull != aParent)
@ -904,9 +906,9 @@ NS_IMETHODIMP nsEditor::InsertNode(nsIDOMNode * aNode,
}
NS_IMETHODIMP nsEditor::CreateTxnForInsertElement(nsIDOMNode * aNode,
nsIDOMNode * aParent,
PRInt32 aPosition,
InsertElementTxn ** aTxn)
nsIDOMNode * aParent,
PRInt32 aPosition,
InsertElementTxn ** aTxn)
{
nsresult result = NS_ERROR_NULL_POINTER;
if (aNode && aParent && aTxn)
@ -997,6 +999,38 @@ nsEditor::InsertText(const nsString& aStringToInsert)
else if (NS_ERROR_EDITOR_NO_SELECTION==result) {
result = DoInitialInsert(aStringToInsert);
}
else if (NS_ERROR_EDITOR_NO_TEXTNODE==result)
{
BeginTransaction();
nsCOMPtr<nsIDOMSelection> selection;
result = GetSelection(getter_AddRefs(selection));
if ((NS_SUCCEEDED(result)) && selection)
{
nsCOMPtr<nsIDOMNode> selectedNode;
PRInt32 offset;
result = selection->GetAnchorNodeAndOffset(getter_AddRefs(selectedNode), &offset);
if ((NS_SUCCEEDED(result)) && selectedNode)
{
nsCOMPtr<nsIDOMNode> newNode;
result = CreateNode(GetTextNodeTag(), selectedNode, offset+1,
getter_AddRefs(newNode));
if (NS_SUCCEEDED(result) && newNode)
{
nsCOMPtr<nsIDOMCharacterData>newTextNode;
newTextNode = do_QueryInterface(newNode);
if (newTextNode)
{
nsAutoString placeholderText(" ");
newTextNode->SetData(placeholderText);
selection->Collapse(newNode, 0);
selection->Extend(newNode, 1);
result = InsertText(aStringToInsert);
}
}
}
}
EndTransaction();
}
return result;
}
@ -1039,6 +1073,9 @@ NS_IMETHODIMP nsEditor::CreateTxnForInsertText(const nsString & aStringToInsert,
result = NS_ERROR_UNEXPECTED;
nodeAsText = do_QueryInterface(node,&result);
range->GetStartOffset(&offset);
if (!nodeAsText) {
result = NS_ERROR_EDITOR_NO_TEXTNODE;
}
}
}
}
@ -1292,7 +1329,7 @@ nsEditor::DeleteSelection(nsIEditor::Direction aDir)
}
NS_IMETHODIMP nsEditor::CreateTxnForDeleteSelection(nsIEditor::Direction aDir,
EditAggregateTxn ** aTxn)
EditAggregateTxn ** aTxn)
{
if (!aTxn)
return NS_ERROR_NULL_POINTER;
@ -1374,7 +1411,8 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
// determine if the insertion point is at the beginning, middle, or end of the node
nsCOMPtr<nsIDOMCharacterData> nodeAsText;
nodeAsText = do_QueryInterface(node, &result);
nsCOMPtr<nsIDOMNode> selectedNode;
nodeAsText = do_QueryInterface(node);
if (nodeAsText)
{
@ -1384,18 +1422,18 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
isLast = PRBool(count==(PRUint32)offset);
}
else
{
nsCOMPtr<nsIDOMNode> sibling;
result = node->GetPreviousSibling(getter_AddRefs(sibling));
if ((NS_SUCCEEDED(result)) && sibling)
isFirst = PR_FALSE;
else
isFirst = PR_TRUE;
result = node->GetNextSibling(getter_AddRefs(sibling));
if ((NS_SUCCEEDED(result)) && sibling)
isLast = PR_FALSE;
else
isLast = PR_TRUE;
{
// get the child list and count
nsCOMPtr<nsIDOMNodeList>childList;
PRUint32 count=0;
result = node->GetChildNodes(getter_AddRefs(childList));
if ((NS_SUCCEEDED(result)) && childList)
{
childList->GetLength(&count);
childList->Item(offset, getter_AddRefs(selectedNode));
}
isFirst = PRBool(0==offset);
isLast = PRBool((count-1)==(PRUint32)offset);
}
// XXX: if isFirst && isLast, then we'll need to delete the node
// as well as the 1 child
@ -1491,6 +1529,11 @@ nsEditor::CreateTxnForDeleteInsertionPoint(nsIDOMRange *aRange,
}
else
{ // we're deleting a node
DeleteElementTxn *txn;
result = CreateTxnForDeleteElement(selectedNode, &txn);
if (NS_SUCCEEDED(result)) {
aTxn->AppendChild(txn);
}
}
}
return result;
@ -1634,13 +1677,12 @@ NS_IMETHODIMP nsEditor::CreateTxnForSplitNode(nsIDOMNode *aNode,
}
NS_IMETHODIMP
nsEditor::JoinNodes(nsIDOMNode * aNodeToKeep,
nsIDOMNode * aNodeToJoin,
nsIDOMNode * aParent,
PRBool aNodeToKeepIsFirst)
nsEditor::JoinNodes(nsIDOMNode * aLeftNode,
nsIDOMNode * aRightNode,
nsIDOMNode * aParent)
{
JoinElementTxn *txn;
nsresult result = CreateTxnForJoinNode(aNodeToKeep, aNodeToJoin, &txn);
nsresult result = CreateTxnForJoinNode(aLeftNode, aRightNode, &txn);
if (NS_SUCCEEDED(result)) {
result = Do(txn);
}
@ -1648,8 +1690,8 @@ nsEditor::JoinNodes(nsIDOMNode * aNodeToKeep,
}
NS_IMETHODIMP nsEditor::CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
nsIDOMNode *aRightNode,
JoinElementTxn **aTxn)
nsIDOMNode *aRightNode,
JoinElementTxn **aTxn)
{
nsresult result=NS_ERROR_NULL_POINTER;
if ((nsnull != aLeftNode) && (nsnull != aRightNode))

Просмотреть файл

@ -126,10 +126,9 @@ public:
PRInt32 aOffset,
nsIDOMNode ** aNewLeftNode);
NS_IMETHOD JoinNodes(nsIDOMNode * aNodeToKeep,
nsIDOMNode * aNodeToJoin,
nsIDOMNode * aParent,
PRBool aNodeToKeepIsFirst);
NS_IMETHOD JoinNodes(nsIDOMNode * aLeftNode,
nsIDOMNode * aRightNode,
nsIDOMNode * aParent);
NS_IMETHOD InsertBreak();

Просмотреть файл

@ -160,7 +160,8 @@ nsTextEditRules::WillInsertText(nsIDOMSelection *aSelection,
(*aTxn)->SetName(InsertTextTxn::gInsertTextTxnName);
mEditor->Do(*aTxn);
}
return WillInsert(aSelection, aCancel);
nsresult result = WillInsert(aSelection, aCancel);
return result;
}
NS_IMETHODIMP
@ -307,6 +308,7 @@ nsTextEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCance
}
// if the document is empty, insert a bogus text node with a &nbsp;
// if we ended up with consecutive text nodes, merge them
NS_IMETHODIMP
nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResult)
{
@ -317,7 +319,7 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul
NS_ASSERTION(PR_TRUE==isCollapsed, "selection not collapsed after delete selection.");
// if the delete selection resulted in no content
// insert a special bogus text node with a &nbsp; character in it.
if (NS_SUCCEEDED(aResult)) // note we're checking aResult, the param that tells us if the insert break happened or not
if (NS_SUCCEEDED(result)) // only do this work if DeleteSelection completed successfully
{
nsCOMPtr<nsIDOMDocument>doc;
mEditor->GetDocument(getter_AddRefs(doc));
@ -384,6 +386,68 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul
}
}
}
// if we don't have an empty document, check the selection to see if any collapsing is necessary
if (!mBogusNode)
{
nsCOMPtr<nsIDOMNode>anchor;
PRInt32 offset;
nsresult result = aSelection->GetAnchorNodeAndOffset(getter_AddRefs(anchor), &offset);
if ((NS_SUCCEEDED(result)) && anchor)
{
nsCOMPtr<nsIDOMNodeList> anchorChildren;
result = anchor->GetChildNodes(getter_AddRefs(anchorChildren));
nsCOMPtr<nsIDOMNode> selectedNode;
if ((NS_SUCCEEDED(result)) && anchorChildren) {
result = anchorChildren->Item(offset, getter_AddRefs(selectedNode));
}
else {
selectedNode = do_QueryInterface(anchor);
}
if ((NS_SUCCEEDED(result)) && selectedNode)
{
nsCOMPtr<nsIDOMCharacterData>selectedNodeAsText;
selectedNodeAsText = do_QueryInterface(selectedNode);
if (selectedNodeAsText)
{
nsCOMPtr<nsIDOMNode> siblingNode;
selectedNode->GetPreviousSibling(getter_AddRefs(siblingNode));
if (siblingNode)
{
nsCOMPtr<nsIDOMCharacterData>siblingNodeAsText;
siblingNodeAsText = do_QueryInterface(siblingNode);
if (siblingNodeAsText)
{
PRUint32 siblingLength; // the length of siblingNode before the join
siblingNodeAsText->GetLength(&siblingLength);
nsCOMPtr<nsIDOMNode> parentNode;
selectedNode->GetParentNode(getter_AddRefs(parentNode));
result = mEditor->JoinNodes(siblingNode, selectedNode, parentNode);
// set selection to point between the end of siblingNode and start of selectedNode
aSelection->Collapse(siblingNode, siblingLength);
selectedNode = do_QueryInterface(siblingNode); // subsequent code relies on selectedNode
// being the real node in the DOM tree
}
}
selectedNode->GetNextSibling(getter_AddRefs(siblingNode));
if (siblingNode)
{
nsCOMPtr<nsIDOMCharacterData>siblingNodeAsText;
siblingNodeAsText = do_QueryInterface(siblingNode);
if (siblingNodeAsText)
{
PRUint32 selectedNodeLength; // the length of siblingNode before the join
selectedNodeAsText->GetLength(&selectedNodeLength);
nsCOMPtr<nsIDOMNode> parentNode;
selectedNode->GetParentNode(getter_AddRefs(parentNode));
result = mEditor->JoinNodes(selectedNode, siblingNode, parentNode);
// set selection
aSelection->Collapse(selectedNode, selectedNodeLength);
}
}
}
}
}
}
}
return result;
}

Просмотреть файл

@ -209,17 +209,16 @@ public:
/**
* JoinNodes() takes 2 nodes and merge their content|children.
* @param aNodeToKeep The node that will remain after the join.
* @param aNodeToJoin The node that will be joined with aNodeToKeep.
* @param aNodeToKeep The left node. It will remain after the join.
* @param aNodeToJoin The right node.
* There is no requirement that the two nodes be of the same type.
* @param aParent The parent of aExistingRightNode
* @param aNodeToKeepIsFirst if PR_TRUE, the contents|children of aNodeToKeep come before the
* contents|children of aNodeToJoin, otherwise their positions are switched.
*/
NS_IMETHOD JoinNodes(nsIDOMNode *aNodeToKeep,
nsIDOMNode *aNodeToJoin,
nsIDOMNode *aParent,
PRBool aNodeToKeepIsFirst)=0;
NS_IMETHOD JoinNodes(nsIDOMNode *aLeftNode,
nsIDOMNode *aRightNode,
nsIDOMNode *aParent)=0;
/**
* Insert a break into the content model.<br>