зеркало из https://github.com/mozilla/pjs.git
fixed join.
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:
Родитель
8db3d855d8
Коммит
5e09828b42
|
@ -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
|
||||
// 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 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
|
||||
// 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 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>
|
||||
|
|
Загрузка…
Ссылка в новой задаче