зеркало из https://github.com/mozilla/gecko-dev.git
Fix for bug 21346.
This commit is contained in:
Родитель
b4b5e28fd5
Коммит
d6e95890c8
|
@ -80,13 +80,13 @@ NS_IMETHODIMP CreateElementTxn::Do(void)
|
|||
}
|
||||
|
||||
NS_ASSERTION(mEditor && mParent, "bad state");
|
||||
if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED;
|
||||
if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED;
|
||||
nsresult result;
|
||||
// create a new node
|
||||
nsCOMPtr<nsIDOMDocument>doc;
|
||||
result = mEditor->GetDocument(getter_AddRefs(doc));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!doc) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!doc) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsAutoString textNodeTag;
|
||||
result = nsEditor::GetTextNodeTag(textNodeTag);
|
||||
|
@ -97,20 +97,20 @@ NS_IMETHODIMP CreateElementTxn::Do(void)
|
|||
const nsString stringData;
|
||||
nsCOMPtr<nsIDOMText>newTextNode;
|
||||
result = doc->CreateTextNode(stringData, getter_AddRefs(newTextNode));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!newTextNode) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!newTextNode) return NS_ERROR_NULL_POINTER;
|
||||
mNewNode = do_QueryInterface(newTextNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement>newElement;
|
||||
result = doc->CreateElement(mTag, getter_AddRefs(newElement));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!newElement) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!newElement) return NS_ERROR_NULL_POINTER;
|
||||
mNewNode = do_QueryInterface(newElement);
|
||||
}
|
||||
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element.");
|
||||
if (!mNewNode) return NS_ERROR_NULL_POINTER;
|
||||
if (!mNewNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (gNoisy) { printf(" newNode = %p\n", mNewNode.get()); }
|
||||
// insert the new node
|
||||
|
@ -130,23 +130,31 @@ NS_IMETHODIMP CreateElementTxn::Do(void)
|
|||
if (mOffsetInParent>count)
|
||||
mOffsetInParent = count;
|
||||
result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode));
|
||||
if (NS_SUCCEEDED(result)) // note, it's ok for mRefNode to be null. that means append
|
||||
if (NS_FAILED(result)) return result; // note, it's ok for mRefNode to be null. that means append
|
||||
|
||||
result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
// only set selection to insertion point if editor gives permission
|
||||
PRBool bAdjustSelection;
|
||||
mEditor->ShouldTxnSetSelection(&bAdjustSelection);
|
||||
if (bAdjustSelection)
|
||||
{
|
||||
result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRInt32 offset=0;
|
||||
result = nsEditor::GetChildOffset(mNewNode, mParent, offset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
PRInt32 offset=0;
|
||||
result = nsEditor::GetChildOffset(mNewNode, mParent, offset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
result = selection->Collapse(mParent, offset+1);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert.");
|
||||
}
|
||||
result = selection->Collapse(mParent, offset+1);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing - dom range gravity will adjust selection
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -158,25 +166,10 @@ NS_IMETHODIMP CreateElementTxn::Undo(void)
|
|||
if (gNoisy) { printf("Undo Create Element, mParent = %p, node = %p\n",
|
||||
mParent.get(), mNewNode.get()); }
|
||||
NS_ASSERTION(mEditor && mParent, "bad state");
|
||||
if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED;
|
||||
if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
nsresult result = mParent->RemoveChild(mNewNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRInt32 offset=0;
|
||||
if (mRefNode) {
|
||||
result = nsEditor::GetChildOffset(mRefNode, mParent, offset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
}
|
||||
result = selection->Collapse(mParent, offset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -184,7 +177,7 @@ NS_IMETHODIMP CreateElementTxn::Redo(void)
|
|||
{
|
||||
if (gNoisy) { printf("Redo Create Element\n"); }
|
||||
NS_ASSERTION(mEditor && mParent, "bad state");
|
||||
if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED;
|
||||
if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
// first, reset mNewNode so it has no attributes or content
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
|
@ -198,19 +191,6 @@ NS_IMETHODIMP CreateElementTxn::Redo(void)
|
|||
// now, reinsert mNewNode
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
nsresult result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
PRInt32 offset=0;
|
||||
result = nsEditor::GetChildOffset(mNewNode, mParent, offset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
result = selection->Collapse(mParent, offset+1);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after redo of insert.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ NS_IMETHODIMP DeleteRangeTxn::Do(void)
|
|||
{
|
||||
if (gNoisy) { printf("Do Delete Range\n"); }
|
||||
if (!mStartParent || !mEndParent || !mCommonParent || !mEditor)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult result;
|
||||
// build the child transactions
|
||||
|
@ -145,14 +145,23 @@ NS_IMETHODIMP DeleteRangeTxn::Do(void)
|
|||
result = EditAggregateTxn::Do();
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// set the resulting selection
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
// only set selection to deletion point if editor gives permission
|
||||
PRBool bAdjustSelection;
|
||||
mEditor->ShouldTxnSetSelection(&bAdjustSelection);
|
||||
if (bAdjustSelection)
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mStartParent, mStartOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing - dom range gravity will adjust selection
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -161,22 +170,9 @@ NS_IMETHODIMP DeleteRangeTxn::Undo(void)
|
|||
{
|
||||
if (gNoisy) { printf("Undo Delete Range\n"); }
|
||||
if (!mStartParent || !mEndParent || !mCommonParent || !mEditor)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult result = EditAggregateTxn::Undo();
|
||||
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
// set the resulting selection
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mStartParent, mStartOffset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
result = selection->Extend(mEndParent, mEndOffset);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -184,19 +180,9 @@ NS_IMETHODIMP DeleteRangeTxn::Redo(void)
|
|||
{
|
||||
if (gNoisy) { printf("Redo Delete Range\n"); }
|
||||
if (!mStartParent || !mEndParent || !mCommonParent || !mEditor)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult result = EditAggregateTxn::Redo();
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// set the resulting selection
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mStartParent, mStartOffset);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -243,8 +229,8 @@ DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
|
|||
{ // if the node is a text node, then delete text content
|
||||
DeleteTextTxn *txn;
|
||||
result = TransactionFactory::GetNewTransaction(DeleteTextTxn::GetCID(), (EditTxn **)&txn);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRInt32 numToDel;
|
||||
if (aStartOffset==aEndOffset)
|
||||
|
@ -259,8 +245,8 @@ DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
|
|||
PRUint32 childCount;
|
||||
nsCOMPtr<nsIDOMNodeList> children;
|
||||
result = aStartParent->GetChildNodes(getter_AddRefs(children));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!children) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!children) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
children->GetLength(&childCount);
|
||||
NS_ASSERTION(aEndOffset<=childCount, "bad aEndOffset");
|
||||
|
@ -269,13 +255,13 @@ DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
|
|||
{
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
result = children->Item(i, getter_AddRefs(child));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!child) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!child) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
DeleteElementTxn *txn;
|
||||
result = TransactionFactory::GetNewTransaction(DeleteElementTxn::GetCID(), (EditTxn **)&txn);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
txn->Init(child);
|
||||
AppendChild(txn);
|
||||
|
@ -311,8 +297,8 @@ NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteContent(nsIDOMNode *aParent,
|
|||
{
|
||||
DeleteTextTxn *txn;
|
||||
result = TransactionFactory::GetNewTransaction(DeleteTextTxn::GetCID(), (EditTxn **)&txn);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
txn->Init(mEditor, textNode, start, numToDelete);
|
||||
AppendChild(txn);
|
||||
|
@ -335,8 +321,8 @@ NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteNodesBetween()
|
|||
nsnull,
|
||||
nsIContentIterator::GetIID(),
|
||||
getter_AddRefs(iter));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!iter) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!iter) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
result = iter->Init(mRange);
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
@ -347,13 +333,13 @@ NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteNodesBetween()
|
|||
nsCOMPtr<nsIContent> content;
|
||||
result = iter->CurrentNode(getter_AddRefs(content));
|
||||
node = do_QueryInterface(content);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!node) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!node) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
DeleteElementTxn *txn;
|
||||
result = TransactionFactory::GetNewTransaction(DeleteElementTxn::GetCID(), (EditTxn **)&txn);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
txn->Init(node);
|
||||
AppendChild(txn);
|
||||
|
|
|
@ -71,14 +71,23 @@ NS_IMETHODIMP DeleteTextTxn::Do(void)
|
|||
nsresult result = mElement->SubstringData(mOffset, mNumCharsToDelete, mDeletedText);
|
||||
NS_ASSERTION(NS_SUCCEEDED(result), "could not get text to delete.");
|
||||
result = mElement->DeleteData(mOffset, mNumCharsToDelete);
|
||||
if (NS_SUCCEEDED(result))
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
// only set selection to deletion point if editor gives permission
|
||||
PRBool bAdjustSelection;
|
||||
mEditor->ShouldTxnSetSelection(&bAdjustSelection);
|
||||
if (bAdjustSelection)
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mElement, mOffset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert.");
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of deletetext.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing - dom range gravity will adjust selection
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -93,15 +102,6 @@ NS_IMETHODIMP DeleteTextTxn::Undo(void)
|
|||
|
||||
nsresult result;
|
||||
result = mElement->InsertData(mOffset, mDeletedText);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mElement, mOffset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -103,16 +103,25 @@ NS_IMETHODIMP InsertElementTxn::Do(void)
|
|||
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
result = mParent->InsertBefore(mNode, refNode, getter_AddRefs(resultNode));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!resultNode) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!resultNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
// place the selection just after the inserted element
|
||||
selection->Collapse(mParent, mOffset+1);
|
||||
//selection->Extend(mParent, mOffset+1);
|
||||
// only set selection to insertion point if editor gives permission
|
||||
PRBool bAdjustSelection;
|
||||
mEditor->ShouldTxnSetSelection(&bAdjustSelection);
|
||||
if (bAdjustSelection)
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
// place the selection just after the inserted element
|
||||
selection->Collapse(mParent, mOffset+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing - dom range gravity will adjust selection
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ InsertTextTxn::~InsertTextTxn()
|
|||
NS_IMETHODIMP InsertTextTxn::Init(nsIDOMCharacterData *aElement,
|
||||
PRUint32 aOffset,
|
||||
const nsString &aStringToInsert,
|
||||
nsWeakPtr aPresShellWeak)
|
||||
nsIEditor *aEditor)
|
||||
{
|
||||
#if 0 //def DEBUG_cmanske
|
||||
nsAutoString text;
|
||||
|
@ -74,58 +74,54 @@ NS_IMETHODIMP InsertTextTxn::Init(nsIDOMCharacterData *aElement,
|
|||
printf("\n");
|
||||
#endif
|
||||
|
||||
NS_ASSERTION(aElement && aPresShellWeak, "bad args");
|
||||
if (!aElement || !aPresShellWeak) return NS_ERROR_NULL_POINTER;
|
||||
NS_ASSERTION(aElement && aEditor, "bad args");
|
||||
if (!aElement || !aEditor) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
mElement = do_QueryInterface(aElement);
|
||||
mOffset = aOffset;
|
||||
mStringToInsert = aStringToInsert;
|
||||
mPresShellWeak = aPresShellWeak;
|
||||
mEditor = aEditor;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP InsertTextTxn::Do(void)
|
||||
{
|
||||
if (gNoisy) { printf("Do Insert Text element = %p\n", mElement.get()); }
|
||||
NS_ASSERTION(mElement && mPresShellWeak, "bad state");
|
||||
if (!mElement || !mPresShellWeak) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
||||
if (!ps) return NS_ERROR_NOT_INITIALIZED;
|
||||
NS_ASSERTION(mElement && mEditor, "bad state");
|
||||
if (!mElement || !mEditor) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
|
||||
// advance caret: This requires the presentation shell to get the selection.
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
nsresult result = ps->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection));
|
||||
nsresult result = mElement->InsertData(mOffset, mStringToInsert);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = mElement->InsertData(mOffset, mStringToInsert);
|
||||
if (NS_SUCCEEDED(result))
|
||||
|
||||
// only set selection to insertion point if editor gives permission
|
||||
PRBool bAdjustSelection;
|
||||
mEditor->ShouldTxnSetSelection(&bAdjustSelection);
|
||||
if (bAdjustSelection)
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mElement, mOffset+mStringToInsert.Length());
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing - dom range gravity will adjust selection
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP InsertTextTxn::Undo(void)
|
||||
{
|
||||
if (gNoisy) { printf("Undo Insert Text element = %p\n", mElement.get()); }
|
||||
NS_ASSERTION(mElement && mPresShellWeak, "bad state");
|
||||
if (!mElement || !mPresShellWeak) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
||||
if (!ps) return NS_ERROR_NOT_INITIALIZED;
|
||||
NS_ASSERTION(mElement && mEditor, "bad state");
|
||||
if (!mElement || !mEditor) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
|
||||
nsresult result;
|
||||
PRUint32 length = mStringToInsert.Length();
|
||||
result = mElement->DeleteData(mOffset, length);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{ // set the selection to the insertion point where the string was removed
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = ps->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mElement, mOffset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
#include "EditTxn.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsWeakPtr.h"
|
||||
|
||||
#define INSERT_TEXT_TXN_CID \
|
||||
{/* 93276f00-ab2c-11d2-8f4b-006008159b0c*/ \
|
||||
|
@ -60,7 +60,7 @@ public:
|
|||
NS_IMETHOD Init(nsIDOMCharacterData *aElement,
|
||||
PRUint32 aOffset,
|
||||
const nsString& aString,
|
||||
nsWeakPtr aPresShellWeak);
|
||||
nsIEditor *aEditor);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -110,8 +110,8 @@ protected:
|
|||
/** the text to insert into mElement at mOffset */
|
||||
nsString mStringToInsert;
|
||||
|
||||
/** the presentation shell, which we'll need to get the selection */
|
||||
nsWeakPtr mPresShellWeak; // weak reference to the nsIPresShell
|
||||
/** the editor, which we'll need to get the selection */
|
||||
nsIEditor *mEditor;
|
||||
|
||||
friend class TransactionFactory;
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "nsEditor.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gNoisy = PR_FALSE;
|
||||
|
@ -39,12 +38,12 @@ JoinElementTxn::JoinElementTxn()
|
|||
/* log description initialized in parent constructor */
|
||||
}
|
||||
|
||||
NS_IMETHODIMP JoinElementTxn::Init(nsIEditor *aEditor,
|
||||
NS_IMETHODIMP JoinElementTxn::Init(nsEditor *aEditor,
|
||||
nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aRightNode)
|
||||
{
|
||||
NS_PRECONDITION((aEditor && aLeftNode && aRightNode), "null arg");
|
||||
if (!aEditor || !aLeftNode || !aRightNode) { return NS_ERROR_NULL_POINTER; }
|
||||
NS_PRECONDITION((aEditor && aLeftNode && aRightNode), "null arg");
|
||||
if (!aEditor || !aLeftNode || !aRightNode) { return NS_ERROR_NULL_POINTER; }
|
||||
mEditor = aEditor;
|
||||
mLeftNode = do_QueryInterface(aLeftNode);
|
||||
mRightNode = do_QueryInterface(aRightNode);
|
||||
|
@ -60,20 +59,20 @@ JoinElementTxn::~JoinElementTxn()
|
|||
NS_IMETHODIMP JoinElementTxn::Do(void)
|
||||
{
|
||||
if (gNoisy) { printf("%p Do Join of %p and %p\n", this, mLeftNode.get(), mRightNode.get()); }
|
||||
NS_PRECONDITION((mEditor && mLeftNode && mRightNode), "null arg");
|
||||
if (!mEditor || !mLeftNode || !mRightNode) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
NS_PRECONDITION((mEditor && mLeftNode && mRightNode), "null arg");
|
||||
if (!mEditor || !mLeftNode || !mRightNode) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
|
||||
// get the parent node
|
||||
nsCOMPtr<nsIDOMNode>leftParent;
|
||||
nsresult result = mLeftNode->GetParentNode(getter_AddRefs(leftParent));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!leftParent) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!leftParent) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// verify that mLeftNode and mRightNode have the same parent
|
||||
nsCOMPtr<nsIDOMNode>rightParent;
|
||||
result = mRightNode->GetParentNode(getter_AddRefs(rightParent));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!rightParent) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!rightParent) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (leftParent==rightParent)
|
||||
{
|
||||
|
@ -89,21 +88,16 @@ NS_IMETHODIMP JoinElementTxn::Do(void)
|
|||
{
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = mLeftNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (childNodes)
|
||||
{
|
||||
childNodes->GetLength(&mOffset);
|
||||
}
|
||||
}
|
||||
result = nsEditor::JoinNodesImpl(mRightNode, mLeftNode, mParent, PR_FALSE);
|
||||
result = mEditor->JoinNodesImpl(mRightNode, mLeftNode, mParent, PR_FALSE);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (gNoisy) { printf(" left node = %p removed\n", mLeftNode.get()); }
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
selection->Collapse(mRightNode, mOffset);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
0x9bc5f9f0, 0xac48, 0x11d2, \
|
||||
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||
|
||||
class nsEditor;
|
||||
|
||||
/**
|
||||
* A transaction that joins two elements E1 (left node) and E2 (right node)
|
||||
|
@ -51,7 +52,7 @@ public:
|
|||
* @param aLeftNode the first of two nodes to join
|
||||
* @param aRightNode the second of two nodes to join
|
||||
*/
|
||||
NS_IMETHOD Init(nsIEditor *aEditor,
|
||||
NS_IMETHOD Init(nsEditor *aEditor,
|
||||
nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aRightNode);
|
||||
protected:
|
||||
|
@ -95,7 +96,7 @@ protected:
|
|||
|
||||
/** the parent node containing mLeftNode and mRightNode */
|
||||
nsCOMPtr<nsIDOMNode> mParent;
|
||||
nsIEditor* mEditor;
|
||||
nsEditor* mEditor;
|
||||
|
||||
friend class TransactionFactory;
|
||||
|
||||
|
|
|
@ -41,12 +41,12 @@ SplitElementTxn::SplitElementTxn()
|
|||
/* log description initialized in parent constructor */
|
||||
}
|
||||
|
||||
NS_IMETHODIMP SplitElementTxn::Init(nsIEditor *aEditor,
|
||||
NS_IMETHODIMP SplitElementTxn::Init(nsEditor *aEditor,
|
||||
nsIDOMNode *aNode,
|
||||
PRInt32 aOffset)
|
||||
{
|
||||
NS_ASSERTION(aEditor && aNode, "bad args");
|
||||
if (!aEditor || !aNode) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
NS_ASSERTION(aEditor && aNode, "bad args");
|
||||
if (!aEditor || !aNode) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
|
||||
mEditor = aEditor;
|
||||
mExistingRightNode = do_QueryInterface(aNode);
|
||||
|
@ -67,17 +67,17 @@ NS_IMETHODIMP SplitElementTxn::Do(void)
|
|||
// create a new node
|
||||
nsresult result = mExistingRightNode->CloneNode(PR_FALSE, getter_AddRefs(mNewLeftNode));
|
||||
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewLeftNode)), "could not create element.");
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!mNewLeftNode) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!mNewLeftNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (gNoisy) { printf(" created left node = %p\n", mNewLeftNode.get()); }
|
||||
// get the parent node
|
||||
result = mExistingRightNode->GetParentNode(getter_AddRefs(mParent));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!mParent) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!mParent) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// insert the new node
|
||||
result = nsEditor::SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
result = mEditor->SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
if (NS_SUCCEEDED(result) && mNewLeftNode)
|
||||
{
|
||||
// Insert formatting whitespace for the new node:
|
||||
|
@ -85,8 +85,8 @@ NS_IMETHODIMP SplitElementTxn::Do(void)
|
|||
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mNewLeftNode, mOffset);
|
||||
}
|
||||
else {
|
||||
|
@ -107,8 +107,7 @@ NS_IMETHODIMP SplitElementTxn::Undo(void)
|
|||
}
|
||||
|
||||
// this assumes Do inserted the new node in front of the prior existing node
|
||||
nsresult result;
|
||||
result = nsEditor::JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
|
||||
nsresult result = mEditor->JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("** after join left child node %p into right node %p\n", mNewLeftNode.get(), mExistingRightNode.get());
|
||||
|
@ -117,14 +116,6 @@ NS_IMETHODIMP SplitElementTxn::Undo(void)
|
|||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (gNoisy) { printf(" left node = %p removed\n", mNewLeftNode.get()); }
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mExistingRightNode, mOffset);
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
0x690c6290, 0xac48, 0x11d2, \
|
||||
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||
|
||||
class nsEditor;
|
||||
|
||||
/**
|
||||
* A transaction that splits an element E into two identical nodes, E1 and E2
|
||||
* with the children of E divided between E1 and E2.
|
||||
|
@ -50,7 +52,7 @@ public:
|
|||
* aOffset may refer to children of aNode, or content of aNode.
|
||||
* The left node will have child|content 0..aOffset-1.
|
||||
*/
|
||||
NS_IMETHOD Init (nsIEditor *aEditor,
|
||||
NS_IMETHOD Init (nsEditor *aEditor,
|
||||
nsIDOMNode *aNode,
|
||||
PRInt32 aOffset);
|
||||
protected:
|
||||
|
@ -93,7 +95,7 @@ protected:
|
|||
|
||||
/** the parent shared by mExistingRightNode and mNewLeftNode */
|
||||
nsCOMPtr<nsIDOMNode> mParent;
|
||||
nsIEditor* mEditor;
|
||||
nsEditor* mEditor;
|
||||
|
||||
friend class TransactionFactory;
|
||||
|
||||
|
|
|
@ -632,6 +632,14 @@ nsEditor::EndPlaceHolderTransaction()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsEditor::ShouldTxnSetSelection(PRBool *aResult)
|
||||
{
|
||||
if (!aResult) return NS_ERROR_NULL_POINTER;
|
||||
*aResult = mShouldTxnSetSelection;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// XXX: the rule system should tell us which node to select all on (ie, the root, or the body)
|
||||
NS_IMETHODIMP nsEditor::SelectAll()
|
||||
{
|
||||
|
@ -1743,24 +1751,24 @@ NS_IMETHODIMP nsEditor::InsertTextImpl(const nsString& aStringToInsert)
|
|||
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
EditTxn *txn;
|
||||
if (mInIMEMode)
|
||||
{
|
||||
if (!mIMETextNode)
|
||||
{
|
||||
EditTxn *txn;
|
||||
if (mInIMEMode)
|
||||
{
|
||||
if (!mIMETextNode)
|
||||
{
|
||||
mIMETextNode = nodeAsText;
|
||||
mIMETextOffset = offset;
|
||||
}
|
||||
result = CreateTxnForIMEText(aStringToInsert,(IMETextTxn**)&txn);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = CreateTxnForInsertText(aStringToInsert, nodeAsText, offset, (InsertTextTxn**)&txn);
|
||||
}
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// let listeners know whats up
|
||||
result = CreateTxnForIMEText(aStringToInsert,(IMETextTxn**)&txn);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = CreateTxnForInsertText(aStringToInsert, nodeAsText, offset, (InsertTextTxn**)&txn);
|
||||
}
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// let listeners know whats up
|
||||
PRInt32 i;
|
||||
nsIEditActionListener *listener;
|
||||
if (mActionListeners)
|
||||
|
@ -1780,7 +1788,7 @@ NS_IMETHODIMP nsEditor::InsertTextImpl(const nsString& aStringToInsert)
|
|||
NS_IF_RELEASE(txn);
|
||||
EndUpdateViewBatch();
|
||||
|
||||
// let listeners know what happened
|
||||
// let listeners know what happened
|
||||
if (mActionListeners)
|
||||
{
|
||||
for (i = 0; i < mActionListeners->Count(); i++)
|
||||
|
@ -2024,10 +2032,11 @@ NS_IMETHODIMP nsEditor::CreateTxnForInsertText(const nsString & aStringToInsert,
|
|||
result = TransactionFactory::GetNewTransaction(InsertTextTxn::GetCID(), (EditTxn **)aTxn);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!*aTxn) return NS_ERROR_OUT_OF_MEMORY;
|
||||
result = (*aTxn)->Init(aTextNode, aOffset, aStringToInsert, mPresShellWeak);
|
||||
result = (*aTxn)->Init(aTextNode, aOffset, aStringToInsert, this);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsEditor::DeleteText(nsIDOMCharacterData *aElement,
|
||||
PRUint32 aOffset,
|
||||
PRUint32 aLength)
|
||||
|
@ -2037,7 +2046,7 @@ NS_IMETHODIMP nsEditor::DeleteText(nsIDOMCharacterData *aElement,
|
|||
nsAutoRules beginRulesSniffing(this, kOpDeleteText, nsIEditor::ePrevious);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
// let listeners know whats up
|
||||
// let listeners know whats up
|
||||
PRInt32 i;
|
||||
nsIEditActionListener *listener;
|
||||
if (mActionListeners)
|
||||
|
@ -2052,7 +2061,7 @@ NS_IMETHODIMP nsEditor::DeleteText(nsIDOMCharacterData *aElement,
|
|||
|
||||
result = Do(txn);
|
||||
|
||||
// let listeners know what happened
|
||||
// let listeners know what happened
|
||||
if (mActionListeners)
|
||||
{
|
||||
for (i = 0; i < mActionListeners->Count(); i++)
|
||||
|
@ -2127,7 +2136,7 @@ NS_IMETHODIMP nsEditor::CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
|
|||
#pragma mark -
|
||||
#endif
|
||||
|
||||
// BEGIN nsEditor public static helper methods
|
||||
// BEGIN nsEditor public helper methods
|
||||
|
||||
nsresult
|
||||
nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
||||
|
@ -2147,6 +2156,20 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
|||
(nsnull!=aNewLeftNode) &&
|
||||
(nsnull!=aParent))
|
||||
{
|
||||
// get selection
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// remember some selection points
|
||||
nsCOMPtr<nsIDOMNode> selStartNode, selEndNode;
|
||||
PRInt32 selStartOffset, selEndOffset;
|
||||
result = GetStartNodeAndOffset(selection, &selStartNode, &selStartOffset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
result = GetEndNodeAndOffset(selection, &selEndNode, &selEndOffset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
result = aParent->InsertBefore(aNewLeftNode, aExistingRightNode, getter_AddRefs(resultNode));
|
||||
//printf(" after insert\n"); content->List(); // DEBUG
|
||||
|
@ -2197,6 +2220,41 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
|||
}
|
||||
}
|
||||
}
|
||||
// handle selection
|
||||
if (GetShouldTxnSetSelection())
|
||||
{
|
||||
// editor wants us to set selection at split point
|
||||
selection->Collapse(aNewLeftNode, aOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
// and adjust the selection if needed
|
||||
// HACK: this is overly simplified - multi-range selections need more work than this
|
||||
if (selStartNode == aExistingRightNode)
|
||||
{
|
||||
if (selStartOffset < aOffset)
|
||||
{
|
||||
selStartNode = aNewLeftNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
selStartOffset -= aOffset;
|
||||
}
|
||||
}
|
||||
if (selEndNode == aExistingRightNode)
|
||||
{
|
||||
if (selEndOffset < aOffset)
|
||||
{
|
||||
selEndNode = aNewLeftNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
selEndOffset -= aOffset;
|
||||
}
|
||||
}
|
||||
selection->Collapse(selStartNode,selStartOffset);
|
||||
selection->Extend(selEndNode,selEndOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2213,14 +2271,28 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
|||
PRBool aNodeToKeepIsFirst)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
NS_ASSERTION(((nsnull!=aNodeToKeep) &&
|
||||
(nsnull!=aNodeToJoin) &&
|
||||
(nsnull!=aParent)),
|
||||
"null arg");
|
||||
if ((nsnull!=aNodeToKeep) &&
|
||||
(nsnull!=aNodeToJoin) &&
|
||||
(nsnull!=aParent))
|
||||
NS_ASSERTION(aNodeToKeep && aNodeToJoin && aParent, "null arg");
|
||||
if (aNodeToKeep && aNodeToJoin && aParent)
|
||||
{
|
||||
// get selection
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// remember some selection points
|
||||
nsCOMPtr<nsIDOMNode> selStartNode, selEndNode;
|
||||
PRInt32 selStartOffset, selEndOffset;
|
||||
result = GetStartNodeAndOffset(selection, &selStartNode, &selStartOffset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
result = GetEndNodeAndOffset(selection, &selEndNode, &selEndOffset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
PRUint32 firstNodeLength;
|
||||
nsCOMPtr<nsIDOMNode> leftNode = aNodeToJoin;
|
||||
if (aNodeToKeepIsFirst) leftNode = aNodeToKeep;
|
||||
result = GetLengthOfDOMNode(leftNode, firstNodeLength);
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
// if it's a text node, just shuffle around some text
|
||||
nsCOMPtr<nsIDOMCharacterData> keepNodeAsText( do_QueryInterface(aNodeToKeep) );
|
||||
nsCOMPtr<nsIDOMCharacterData> joinNodeAsText( do_QueryInterface(aNodeToJoin) );
|
||||
|
@ -2249,9 +2321,9 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
|||
{
|
||||
PRInt32 i; // must be signed int!
|
||||
PRUint32 childCount=0;
|
||||
childNodes->GetLength(&childCount);
|
||||
nsCOMPtr<nsIDOMNode> firstNode; //only used if aNodeToKeepIsFirst is false
|
||||
if (PR_FALSE==aNodeToKeepIsFirst)
|
||||
childNodes->GetLength(&childCount);
|
||||
if (!aNodeToKeepIsFirst)
|
||||
{ // remember the first child in aNodeToKeep, we'll insert all the children of aNodeToJoin in front of it
|
||||
result = aNodeToKeep->GetFirstChild(getter_AddRefs(firstNode));
|
||||
// GetFirstChild returns nsnull firstNode if aNodeToKeep has no children, that's ok.
|
||||
|
@ -2265,7 +2337,7 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
|||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||
{
|
||||
if (PR_TRUE==aNodeToKeepIsFirst)
|
||||
if (aNodeToKeepIsFirst)
|
||||
{ // append children of aNodeToJoin
|
||||
//was result = aNodeToKeep->AppendChild(childNode, getter_AddRefs(resultNode));
|
||||
result = aNodeToKeep->InsertBefore(childNode, previousChild, getter_AddRefs(resultNode));
|
||||
|
@ -2288,6 +2360,35 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
|||
{ // delete the extra node
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
result = aParent->RemoveChild(aNodeToJoin, getter_AddRefs(resultNode));
|
||||
|
||||
if (GetShouldTxnSetSelection())
|
||||
{
|
||||
// editor wants us to set selection at join point
|
||||
selection->Collapse(aNodeToKeep, firstNodeLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
// and adjust the selection if needed
|
||||
// HACK: this is overly simplified - multi-range selections need more work than this
|
||||
if (selStartNode == aNodeToJoin)
|
||||
{
|
||||
selStartNode = aNodeToKeep;
|
||||
if (aNodeToKeepIsFirst)
|
||||
{
|
||||
selStartOffset += firstNodeLength;
|
||||
}
|
||||
}
|
||||
if (selEndNode == aNodeToJoin)
|
||||
{
|
||||
selEndNode = aNodeToKeep;
|
||||
if (aNodeToKeepIsFirst)
|
||||
{
|
||||
selEndOffset += firstNodeLength;
|
||||
}
|
||||
}
|
||||
selection->Collapse(selStartNode,selStartOffset);
|
||||
selection->Extend(selEndNode,selEndOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -3998,13 +4099,13 @@ nsresult nsEditor::EndUpdateViewBatch()
|
|||
{
|
||||
NS_PRECONDITION(mUpdateCount>0, "bad state");
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
nsresult rv = GetPresShell(getter_AddRefs(presShell));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
StCaretHider caretHider(presShell);
|
||||
|
||||
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
nsresult selectionResult = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(selectionResult) && selection) {
|
||||
|
@ -4028,6 +4129,18 @@ nsresult nsEditor::EndUpdateViewBatch()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEditor::GetShouldTxnSetSelection()
|
||||
{
|
||||
return mShouldTxnSetSelection;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsEditor::SetShouldTxnSetSelection(PRBool aShould)
|
||||
{
|
||||
mShouldTxnSetSelection = aShould;
|
||||
}
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
|
@ -4270,7 +4383,7 @@ nsEditor::CreateTxnForIMEText(const nsString & aStringToInsert,
|
|||
{
|
||||
NS_ASSERTION(aTxn, "illegal value- null ptr- aTxn");
|
||||
if(!aTxn) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
|
||||
nsresult result;
|
||||
|
||||
result = TransactionFactory::GetNewTransaction(IMETextTxn::GetCID(), (EditTxn **)aTxn);
|
||||
|
|
|
@ -142,6 +142,7 @@ public:
|
|||
|
||||
NS_IMETHOD BeginPlaceHolderTransaction(nsIAtom *aName);
|
||||
NS_IMETHOD EndPlaceHolderTransaction();
|
||||
NS_IMETHOD ShouldTxnSetSelection(PRBool *aResult);
|
||||
|
||||
// pure virtual, because the definition of 'empty' depends on the doc type
|
||||
NS_IMETHOD GetDocumentIsEmpty(PRBool *aDocumentIsEmpty)=0;
|
||||
|
@ -396,10 +397,10 @@ public:
|
|||
* @param aNewLeftNode [OUT] the new node resulting from the split, becomes aExistingRightNode's previous sibling.
|
||||
* @param aParent the parent of aExistingRightNode
|
||||
*/
|
||||
static nsresult SplitNodeImpl(nsIDOMNode *aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode *aNewLeftNode,
|
||||
nsIDOMNode *aParent);
|
||||
nsresult SplitNodeImpl(nsIDOMNode *aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode *aNewLeftNode,
|
||||
nsIDOMNode *aParent);
|
||||
|
||||
/**
|
||||
* JoinNodes() takes 2 nodes and merge their content|children.
|
||||
|
@ -410,10 +411,10 @@ public:
|
|||
* @param aNodeToKeepIsFirst if PR_TRUE, the contents|children of aNodeToKeep come before the
|
||||
* contents|children of aNodeToJoin, otherwise their positions are switched.
|
||||
*/
|
||||
static nsresult JoinNodesImpl(nsIDOMNode *aNodeToKeep,
|
||||
nsIDOMNode *aNodeToJoin,
|
||||
nsIDOMNode *aParent,
|
||||
PRBool aNodeToKeepIsFirst);
|
||||
nsresult JoinNodesImpl(nsIDOMNode *aNodeToKeep,
|
||||
nsIDOMNode *aNodeToJoin,
|
||||
nsIDOMNode *aParent,
|
||||
PRBool aNodeToKeepIsFirst);
|
||||
|
||||
/**
|
||||
* Set aOffset to the offset of aChild in aParent.
|
||||
|
@ -629,6 +630,8 @@ public:
|
|||
nsresult BeginUpdateViewBatch(void);
|
||||
nsresult EndUpdateViewBatch(void);
|
||||
|
||||
PRBool GetShouldTxnSetSelection();
|
||||
void SetShouldTxnSetSelection(PRBool aShould);
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -645,7 +648,7 @@ protected:
|
|||
PRInt32 mPlaceHolderBatch; // nesting count for batching
|
||||
nsCOMPtr<nsIDOMNode> mTxnStartNode; // saved selection info to pass to placeholder at init time
|
||||
PRInt32 mTxnStartOffset; // " " " "
|
||||
|
||||
PRBool mShouldTxnSetSelection; // turn off for conservative selection adjustment by txns
|
||||
//
|
||||
// data necessary to build IME transactions
|
||||
//
|
||||
|
@ -666,6 +669,7 @@ protected:
|
|||
static PRInt32 gInstanceCount;
|
||||
|
||||
friend PRBool NSCanUnload(nsISupports* serviceMgr);
|
||||
friend class nsAutoTxnsConserveSelection;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -107,5 +107,36 @@ class nsAutoRules
|
|||
};
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* stack based helper class for turning off active selection adjustment
|
||||
* by low level transactions
|
||||
*/
|
||||
class nsAutoTxnsConserveSelection
|
||||
{
|
||||
public:
|
||||
|
||||
nsAutoTxnsConserveSelection(nsEditor *ed) : mEd(ed), mOldState(PR_TRUE)
|
||||
{
|
||||
if (mEd)
|
||||
{
|
||||
mOldState = mEd->GetShouldTxnSetSelection();
|
||||
mEd->SetShouldTxnSetSelection(PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
~nsAutoTxnsConserveSelection()
|
||||
{
|
||||
if (mEd)
|
||||
{
|
||||
mEd->SetShouldTxnSetSelection(mOldState);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
nsEditor *mEd;
|
||||
PRBool mOldState;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // nsEditorUtils_h__
|
||||
|
|
|
@ -153,6 +153,8 @@ nsHTMLEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
|||
|
||||
if (mDocChangeRange && !((action == nsEditor::kOpUndo) || (action == nsEditor::kOpRedo)))
|
||||
{
|
||||
nsAutoTxnsConserveSelection dontSpazMySelection(mEditor);
|
||||
|
||||
// expand the "changed doc range" as needed
|
||||
res = PromoteRange(mDocChangeRange, action);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
@ -2687,7 +2689,7 @@ nsHTMLEditRules::ReplaceContainer(nsIDOMNode *inNode,
|
|||
// the parent of inNode
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::RemoveContainer(nsIDOMNode *inNode)
|
||||
nsHTMLEditRules::RemoveContainer(nsIDOMNode *inNode, PRBool aAddBRIfNeeded)
|
||||
{
|
||||
if (!inNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
@ -2698,6 +2700,38 @@ nsHTMLEditRules::RemoveContainer(nsIDOMNode *inNode)
|
|||
PRInt32 offset;
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// add BR's before and/or after the inNode
|
||||
// if aAddBRIfNeeded is set and if the content
|
||||
// before/after the node is inline.
|
||||
// Only do this if inNode is a block node.
|
||||
if (aAddBRIfNeeded && mEditor->IsBlockNode(inNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> nearNode, brNode;
|
||||
res = GetPriorHTMLSibling(inNode, &nearNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nearNode && mEditor->IsInlineNode(nearNode))
|
||||
{
|
||||
res = mEditor->CreateBR(parent, offset, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// refresh location info
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
res = GetNextHTMLSibling(inNode, &nearNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nearNode && mEditor->IsInlineNode(nearNode))
|
||||
{
|
||||
res = mEditor->CreateBR(parent, offset+1, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// refresh location info
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
|
||||
// loop through the child nodes of inNode and promote them
|
||||
// into inNode's parent.
|
||||
PRBool bHasMoreChildren;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
|
@ -3249,7 +3283,7 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString
|
|||
|
||||
// we special case an empty tag name to mean "remove block parents".
|
||||
// This is used for the "normal" paragraph style in mail-compose
|
||||
if (aBlockTag->IsEmpty()) bNoParent = PR_TRUE;
|
||||
if (aBlockTag->IsEmpty() || *aBlockTag=="normal") bNoParent = PR_TRUE;
|
||||
|
||||
arrayOfNodes->Count(&listCount);
|
||||
|
||||
|
@ -3272,11 +3306,6 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString
|
|||
continue; // do nothing to this block
|
||||
}
|
||||
|
||||
// if curNode is a <pre> and we are converting to non-pre, we need
|
||||
// to process the text inside the <pre> so as to convert returns
|
||||
// to breaks, and runs of spaces to nbsps.
|
||||
// xxx floppy moose
|
||||
|
||||
// if curNode is a mozdiv, p, header, address, or pre, replace
|
||||
// it with a new block of correct type.
|
||||
// xxx floppy moose: pre cant hold everything the others can
|
||||
|
@ -3294,10 +3323,10 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString
|
|||
curBlock = 0; // forget any previous block used for previous inline nodes
|
||||
if (bNoParent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
res = mEditor->CreateBR(curParent, offset+1, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = RemoveContainer(curNode);
|
||||
// nsCOMPtr<nsIDOMNode> brNode;
|
||||
// res = mEditor->CreateBR(curParent, offset+1, &brNode);
|
||||
// if (NS_FAILED(res)) return res;
|
||||
res = RemoveContainer(curNode, PR_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4029,10 +4058,22 @@ nsHTMLEditRules::PopListItem(nsIDOMNode *aListItem, PRBool *aOutOfList)
|
|||
// unwrap list item contents if they are no longer in a list
|
||||
if (!IsList(curParPar) && IsListItem(curNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> mozDiv;
|
||||
nsCOMPtr<nsIDOMNode> lastChild;
|
||||
res = GetLastEditableChild(curNode, &lastChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = RemoveContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (mEditor->IsInlineNode(lastChild))
|
||||
{
|
||||
// last thing inside of the listitem wasn't a block node.
|
||||
// insert a BR to preserve the illusion of block boundaries
|
||||
nsCOMPtr<nsIDOMNode> node, brNode;
|
||||
PRInt32 offset;
|
||||
res = nsEditor::GetNodeLocation(lastChild, &node, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->CreateBR(node, offset+1, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
*aOutOfList = PR_TRUE;
|
||||
}
|
||||
return res;
|
||||
|
|
|
@ -133,7 +133,7 @@ protected:
|
|||
nsresult ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString *aBlockTag);
|
||||
|
||||
nsresult ReplaceContainer(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, const nsString &aNodeType);
|
||||
nsresult RemoveContainer(nsIDOMNode *inNode);
|
||||
nsresult RemoveContainer(nsIDOMNode *inNode, PRBool aAddBRIfNeeded=PR_FALSE);
|
||||
nsresult InsertContainerAbove(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, const nsString &aNodeType);
|
||||
|
||||
nsresult JoinNodesSmart( nsIDOMNode *aNodeLeft,
|
||||
|
|
|
@ -1818,13 +1818,9 @@ NS_IMETHODIMP nsHTMLEditor::SetParagraphFormat(const nsString& aParagraphFormat)
|
|||
//Kinda sad to waste memory just to force lower case
|
||||
nsAutoString tag = aParagraphFormat;
|
||||
tag.ToLowerCase();
|
||||
if (tag == "normal")
|
||||
{
|
||||
res = InsertBasicBlock("p");
|
||||
}
|
||||
//XXX: TODO: Do we really want to support setting list types here?
|
||||
// If yes, we need to add "dd", "dt" for <dl> support
|
||||
else if (tag == "li")
|
||||
if (tag == "li")
|
||||
{
|
||||
//XXX: Why do we assume "ul" What about "ol"? This will change an OL into a UL list!
|
||||
res = MakeOrChangeList("ul");
|
||||
|
|
|
@ -1080,9 +1080,6 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection,
|
|||
res = mEditor->JoinNodes(selectedNode, siblingNode, parentNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// selectedNode will remain after the join, siblingNode is removed
|
||||
// set selection
|
||||
res = aSelection->Collapse(siblingNode, selectedNodeLength);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
// if, after all this work, selectedNode is empty, delete it
|
||||
|
|
|
@ -80,13 +80,13 @@ NS_IMETHODIMP CreateElementTxn::Do(void)
|
|||
}
|
||||
|
||||
NS_ASSERTION(mEditor && mParent, "bad state");
|
||||
if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED;
|
||||
if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED;
|
||||
nsresult result;
|
||||
// create a new node
|
||||
nsCOMPtr<nsIDOMDocument>doc;
|
||||
result = mEditor->GetDocument(getter_AddRefs(doc));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!doc) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!doc) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsAutoString textNodeTag;
|
||||
result = nsEditor::GetTextNodeTag(textNodeTag);
|
||||
|
@ -97,20 +97,20 @@ NS_IMETHODIMP CreateElementTxn::Do(void)
|
|||
const nsString stringData;
|
||||
nsCOMPtr<nsIDOMText>newTextNode;
|
||||
result = doc->CreateTextNode(stringData, getter_AddRefs(newTextNode));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!newTextNode) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!newTextNode) return NS_ERROR_NULL_POINTER;
|
||||
mNewNode = do_QueryInterface(newTextNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement>newElement;
|
||||
result = doc->CreateElement(mTag, getter_AddRefs(newElement));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!newElement) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!newElement) return NS_ERROR_NULL_POINTER;
|
||||
mNewNode = do_QueryInterface(newElement);
|
||||
}
|
||||
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element.");
|
||||
if (!mNewNode) return NS_ERROR_NULL_POINTER;
|
||||
if (!mNewNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (gNoisy) { printf(" newNode = %p\n", mNewNode.get()); }
|
||||
// insert the new node
|
||||
|
@ -130,23 +130,31 @@ NS_IMETHODIMP CreateElementTxn::Do(void)
|
|||
if (mOffsetInParent>count)
|
||||
mOffsetInParent = count;
|
||||
result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode));
|
||||
if (NS_SUCCEEDED(result)) // note, it's ok for mRefNode to be null. that means append
|
||||
if (NS_FAILED(result)) return result; // note, it's ok for mRefNode to be null. that means append
|
||||
|
||||
result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
// only set selection to insertion point if editor gives permission
|
||||
PRBool bAdjustSelection;
|
||||
mEditor->ShouldTxnSetSelection(&bAdjustSelection);
|
||||
if (bAdjustSelection)
|
||||
{
|
||||
result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRInt32 offset=0;
|
||||
result = nsEditor::GetChildOffset(mNewNode, mParent, offset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
PRInt32 offset=0;
|
||||
result = nsEditor::GetChildOffset(mNewNode, mParent, offset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
result = selection->Collapse(mParent, offset+1);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert.");
|
||||
}
|
||||
result = selection->Collapse(mParent, offset+1);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing - dom range gravity will adjust selection
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -158,25 +166,10 @@ NS_IMETHODIMP CreateElementTxn::Undo(void)
|
|||
if (gNoisy) { printf("Undo Create Element, mParent = %p, node = %p\n",
|
||||
mParent.get(), mNewNode.get()); }
|
||||
NS_ASSERTION(mEditor && mParent, "bad state");
|
||||
if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED;
|
||||
if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
nsresult result = mParent->RemoveChild(mNewNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRInt32 offset=0;
|
||||
if (mRefNode) {
|
||||
result = nsEditor::GetChildOffset(mRefNode, mParent, offset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
}
|
||||
result = selection->Collapse(mParent, offset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -184,7 +177,7 @@ NS_IMETHODIMP CreateElementTxn::Redo(void)
|
|||
{
|
||||
if (gNoisy) { printf("Redo Create Element\n"); }
|
||||
NS_ASSERTION(mEditor && mParent, "bad state");
|
||||
if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED;
|
||||
if (!mEditor || !mParent) return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
// first, reset mNewNode so it has no attributes or content
|
||||
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
||||
|
@ -198,19 +191,6 @@ NS_IMETHODIMP CreateElementTxn::Redo(void)
|
|||
// now, reinsert mNewNode
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
nsresult result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
PRInt32 offset=0;
|
||||
result = nsEditor::GetChildOffset(mNewNode, mParent, offset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
result = selection->Collapse(mParent, offset+1);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after redo of insert.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ NS_IMETHODIMP DeleteRangeTxn::Do(void)
|
|||
{
|
||||
if (gNoisy) { printf("Do Delete Range\n"); }
|
||||
if (!mStartParent || !mEndParent || !mCommonParent || !mEditor)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult result;
|
||||
// build the child transactions
|
||||
|
@ -145,14 +145,23 @@ NS_IMETHODIMP DeleteRangeTxn::Do(void)
|
|||
result = EditAggregateTxn::Do();
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// set the resulting selection
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
// only set selection to deletion point if editor gives permission
|
||||
PRBool bAdjustSelection;
|
||||
mEditor->ShouldTxnSetSelection(&bAdjustSelection);
|
||||
if (bAdjustSelection)
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mStartParent, mStartOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing - dom range gravity will adjust selection
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -161,22 +170,9 @@ NS_IMETHODIMP DeleteRangeTxn::Undo(void)
|
|||
{
|
||||
if (gNoisy) { printf("Undo Delete Range\n"); }
|
||||
if (!mStartParent || !mEndParent || !mCommonParent || !mEditor)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult result = EditAggregateTxn::Undo();
|
||||
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
// set the resulting selection
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mStartParent, mStartOffset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
result = selection->Extend(mEndParent, mEndOffset);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -184,19 +180,9 @@ NS_IMETHODIMP DeleteRangeTxn::Redo(void)
|
|||
{
|
||||
if (gNoisy) { printf("Redo Delete Range\n"); }
|
||||
if (!mStartParent || !mEndParent || !mCommonParent || !mEditor)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
nsresult result = EditAggregateTxn::Redo();
|
||||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
// set the resulting selection
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mStartParent, mStartOffset);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -243,8 +229,8 @@ DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
|
|||
{ // if the node is a text node, then delete text content
|
||||
DeleteTextTxn *txn;
|
||||
result = TransactionFactory::GetNewTransaction(DeleteTextTxn::GetCID(), (EditTxn **)&txn);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRInt32 numToDel;
|
||||
if (aStartOffset==aEndOffset)
|
||||
|
@ -259,8 +245,8 @@ DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
|
|||
PRUint32 childCount;
|
||||
nsCOMPtr<nsIDOMNodeList> children;
|
||||
result = aStartParent->GetChildNodes(getter_AddRefs(children));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!children) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!children) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
children->GetLength(&childCount);
|
||||
NS_ASSERTION(aEndOffset<=childCount, "bad aEndOffset");
|
||||
|
@ -269,13 +255,13 @@ DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
|
|||
{
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
result = children->Item(i, getter_AddRefs(child));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!child) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!child) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
DeleteElementTxn *txn;
|
||||
result = TransactionFactory::GetNewTransaction(DeleteElementTxn::GetCID(), (EditTxn **)&txn);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
txn->Init(child);
|
||||
AppendChild(txn);
|
||||
|
@ -311,8 +297,8 @@ NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteContent(nsIDOMNode *aParent,
|
|||
{
|
||||
DeleteTextTxn *txn;
|
||||
result = TransactionFactory::GetNewTransaction(DeleteTextTxn::GetCID(), (EditTxn **)&txn);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
txn->Init(mEditor, textNode, start, numToDelete);
|
||||
AppendChild(txn);
|
||||
|
@ -335,8 +321,8 @@ NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteNodesBetween()
|
|||
nsnull,
|
||||
nsIContentIterator::GetIID(),
|
||||
getter_AddRefs(iter));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!iter) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!iter) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
result = iter->Init(mRange);
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
@ -347,13 +333,13 @@ NS_IMETHODIMP DeleteRangeTxn::CreateTxnsToDeleteNodesBetween()
|
|||
nsCOMPtr<nsIContent> content;
|
||||
result = iter->CurrentNode(getter_AddRefs(content));
|
||||
node = do_QueryInterface(content);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!node) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!node) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
DeleteElementTxn *txn;
|
||||
result = TransactionFactory::GetNewTransaction(DeleteElementTxn::GetCID(), (EditTxn **)&txn);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
txn->Init(node);
|
||||
AppendChild(txn);
|
||||
|
|
|
@ -71,14 +71,23 @@ NS_IMETHODIMP DeleteTextTxn::Do(void)
|
|||
nsresult result = mElement->SubstringData(mOffset, mNumCharsToDelete, mDeletedText);
|
||||
NS_ASSERTION(NS_SUCCEEDED(result), "could not get text to delete.");
|
||||
result = mElement->DeleteData(mOffset, mNumCharsToDelete);
|
||||
if (NS_SUCCEEDED(result))
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
// only set selection to deletion point if editor gives permission
|
||||
PRBool bAdjustSelection;
|
||||
mEditor->ShouldTxnSetSelection(&bAdjustSelection);
|
||||
if (bAdjustSelection)
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mElement, mOffset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert.");
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of deletetext.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing - dom range gravity will adjust selection
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -93,15 +102,6 @@ NS_IMETHODIMP DeleteTextTxn::Undo(void)
|
|||
|
||||
nsresult result;
|
||||
result = mElement->InsertData(mOffset, mDeletedText);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mElement, mOffset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -103,16 +103,25 @@ NS_IMETHODIMP InsertElementTxn::Do(void)
|
|||
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
result = mParent->InsertBefore(mNode, refNode, getter_AddRefs(resultNode));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!resultNode) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!resultNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
// place the selection just after the inserted element
|
||||
selection->Collapse(mParent, mOffset+1);
|
||||
//selection->Extend(mParent, mOffset+1);
|
||||
// only set selection to insertion point if editor gives permission
|
||||
PRBool bAdjustSelection;
|
||||
mEditor->ShouldTxnSetSelection(&bAdjustSelection);
|
||||
if (bAdjustSelection)
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
// place the selection just after the inserted element
|
||||
selection->Collapse(mParent, mOffset+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing - dom range gravity will adjust selection
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ InsertTextTxn::~InsertTextTxn()
|
|||
NS_IMETHODIMP InsertTextTxn::Init(nsIDOMCharacterData *aElement,
|
||||
PRUint32 aOffset,
|
||||
const nsString &aStringToInsert,
|
||||
nsWeakPtr aPresShellWeak)
|
||||
nsIEditor *aEditor)
|
||||
{
|
||||
#if 0 //def DEBUG_cmanske
|
||||
nsAutoString text;
|
||||
|
@ -74,58 +74,54 @@ NS_IMETHODIMP InsertTextTxn::Init(nsIDOMCharacterData *aElement,
|
|||
printf("\n");
|
||||
#endif
|
||||
|
||||
NS_ASSERTION(aElement && aPresShellWeak, "bad args");
|
||||
if (!aElement || !aPresShellWeak) return NS_ERROR_NULL_POINTER;
|
||||
NS_ASSERTION(aElement && aEditor, "bad args");
|
||||
if (!aElement || !aEditor) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
mElement = do_QueryInterface(aElement);
|
||||
mOffset = aOffset;
|
||||
mStringToInsert = aStringToInsert;
|
||||
mPresShellWeak = aPresShellWeak;
|
||||
mEditor = aEditor;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP InsertTextTxn::Do(void)
|
||||
{
|
||||
if (gNoisy) { printf("Do Insert Text element = %p\n", mElement.get()); }
|
||||
NS_ASSERTION(mElement && mPresShellWeak, "bad state");
|
||||
if (!mElement || !mPresShellWeak) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
||||
if (!ps) return NS_ERROR_NOT_INITIALIZED;
|
||||
NS_ASSERTION(mElement && mEditor, "bad state");
|
||||
if (!mElement || !mEditor) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
|
||||
// advance caret: This requires the presentation shell to get the selection.
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
nsresult result = ps->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection));
|
||||
nsresult result = mElement->InsertData(mOffset, mStringToInsert);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = mElement->InsertData(mOffset, mStringToInsert);
|
||||
if (NS_SUCCEEDED(result))
|
||||
|
||||
// only set selection to insertion point if editor gives permission
|
||||
PRBool bAdjustSelection;
|
||||
mEditor->ShouldTxnSetSelection(&bAdjustSelection);
|
||||
if (bAdjustSelection)
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mElement, mOffset+mStringToInsert.Length());
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// do nothing - dom range gravity will adjust selection
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP InsertTextTxn::Undo(void)
|
||||
{
|
||||
if (gNoisy) { printf("Undo Insert Text element = %p\n", mElement.get()); }
|
||||
NS_ASSERTION(mElement && mPresShellWeak, "bad state");
|
||||
if (!mElement || !mPresShellWeak) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
|
||||
if (!ps) return NS_ERROR_NOT_INITIALIZED;
|
||||
NS_ASSERTION(mElement && mEditor, "bad state");
|
||||
if (!mElement || !mEditor) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
|
||||
nsresult result;
|
||||
PRUint32 length = mStringToInsert.Length();
|
||||
result = mElement->DeleteData(mOffset, length);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{ // set the selection to the insertion point where the string was removed
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = ps->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mElement, mOffset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
#include "EditTxn.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsWeakPtr.h"
|
||||
|
||||
#define INSERT_TEXT_TXN_CID \
|
||||
{/* 93276f00-ab2c-11d2-8f4b-006008159b0c*/ \
|
||||
|
@ -60,7 +60,7 @@ public:
|
|||
NS_IMETHOD Init(nsIDOMCharacterData *aElement,
|
||||
PRUint32 aOffset,
|
||||
const nsString& aString,
|
||||
nsWeakPtr aPresShellWeak);
|
||||
nsIEditor *aEditor);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -110,8 +110,8 @@ protected:
|
|||
/** the text to insert into mElement at mOffset */
|
||||
nsString mStringToInsert;
|
||||
|
||||
/** the presentation shell, which we'll need to get the selection */
|
||||
nsWeakPtr mPresShellWeak; // weak reference to the nsIPresShell
|
||||
/** the editor, which we'll need to get the selection */
|
||||
nsIEditor *mEditor;
|
||||
|
||||
friend class TransactionFactory;
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "nsEditor.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gNoisy = PR_FALSE;
|
||||
|
@ -39,12 +38,12 @@ JoinElementTxn::JoinElementTxn()
|
|||
/* log description initialized in parent constructor */
|
||||
}
|
||||
|
||||
NS_IMETHODIMP JoinElementTxn::Init(nsIEditor *aEditor,
|
||||
NS_IMETHODIMP JoinElementTxn::Init(nsEditor *aEditor,
|
||||
nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aRightNode)
|
||||
{
|
||||
NS_PRECONDITION((aEditor && aLeftNode && aRightNode), "null arg");
|
||||
if (!aEditor || !aLeftNode || !aRightNode) { return NS_ERROR_NULL_POINTER; }
|
||||
NS_PRECONDITION((aEditor && aLeftNode && aRightNode), "null arg");
|
||||
if (!aEditor || !aLeftNode || !aRightNode) { return NS_ERROR_NULL_POINTER; }
|
||||
mEditor = aEditor;
|
||||
mLeftNode = do_QueryInterface(aLeftNode);
|
||||
mRightNode = do_QueryInterface(aRightNode);
|
||||
|
@ -60,20 +59,20 @@ JoinElementTxn::~JoinElementTxn()
|
|||
NS_IMETHODIMP JoinElementTxn::Do(void)
|
||||
{
|
||||
if (gNoisy) { printf("%p Do Join of %p and %p\n", this, mLeftNode.get(), mRightNode.get()); }
|
||||
NS_PRECONDITION((mEditor && mLeftNode && mRightNode), "null arg");
|
||||
if (!mEditor || !mLeftNode || !mRightNode) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
NS_PRECONDITION((mEditor && mLeftNode && mRightNode), "null arg");
|
||||
if (!mEditor || !mLeftNode || !mRightNode) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
|
||||
// get the parent node
|
||||
nsCOMPtr<nsIDOMNode>leftParent;
|
||||
nsresult result = mLeftNode->GetParentNode(getter_AddRefs(leftParent));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!leftParent) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!leftParent) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// verify that mLeftNode and mRightNode have the same parent
|
||||
nsCOMPtr<nsIDOMNode>rightParent;
|
||||
result = mRightNode->GetParentNode(getter_AddRefs(rightParent));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!rightParent) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!rightParent) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (leftParent==rightParent)
|
||||
{
|
||||
|
@ -89,21 +88,16 @@ NS_IMETHODIMP JoinElementTxn::Do(void)
|
|||
{
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = mLeftNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (childNodes)
|
||||
{
|
||||
childNodes->GetLength(&mOffset);
|
||||
}
|
||||
}
|
||||
result = nsEditor::JoinNodesImpl(mRightNode, mLeftNode, mParent, PR_FALSE);
|
||||
result = mEditor->JoinNodesImpl(mRightNode, mLeftNode, mParent, PR_FALSE);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (gNoisy) { printf(" left node = %p removed\n", mLeftNode.get()); }
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
selection->Collapse(mRightNode, mOffset);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
0x9bc5f9f0, 0xac48, 0x11d2, \
|
||||
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||
|
||||
class nsEditor;
|
||||
|
||||
/**
|
||||
* A transaction that joins two elements E1 (left node) and E2 (right node)
|
||||
|
@ -51,7 +52,7 @@ public:
|
|||
* @param aLeftNode the first of two nodes to join
|
||||
* @param aRightNode the second of two nodes to join
|
||||
*/
|
||||
NS_IMETHOD Init(nsIEditor *aEditor,
|
||||
NS_IMETHOD Init(nsEditor *aEditor,
|
||||
nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aRightNode);
|
||||
protected:
|
||||
|
@ -95,7 +96,7 @@ protected:
|
|||
|
||||
/** the parent node containing mLeftNode and mRightNode */
|
||||
nsCOMPtr<nsIDOMNode> mParent;
|
||||
nsIEditor* mEditor;
|
||||
nsEditor* mEditor;
|
||||
|
||||
friend class TransactionFactory;
|
||||
|
||||
|
|
|
@ -41,12 +41,12 @@ SplitElementTxn::SplitElementTxn()
|
|||
/* log description initialized in parent constructor */
|
||||
}
|
||||
|
||||
NS_IMETHODIMP SplitElementTxn::Init(nsIEditor *aEditor,
|
||||
NS_IMETHODIMP SplitElementTxn::Init(nsEditor *aEditor,
|
||||
nsIDOMNode *aNode,
|
||||
PRInt32 aOffset)
|
||||
{
|
||||
NS_ASSERTION(aEditor && aNode, "bad args");
|
||||
if (!aEditor || !aNode) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
NS_ASSERTION(aEditor && aNode, "bad args");
|
||||
if (!aEditor || !aNode) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
|
||||
mEditor = aEditor;
|
||||
mExistingRightNode = do_QueryInterface(aNode);
|
||||
|
@ -67,17 +67,17 @@ NS_IMETHODIMP SplitElementTxn::Do(void)
|
|||
// create a new node
|
||||
nsresult result = mExistingRightNode->CloneNode(PR_FALSE, getter_AddRefs(mNewLeftNode));
|
||||
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewLeftNode)), "could not create element.");
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!mNewLeftNode) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!mNewLeftNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (gNoisy) { printf(" created left node = %p\n", mNewLeftNode.get()); }
|
||||
// get the parent node
|
||||
result = mExistingRightNode->GetParentNode(getter_AddRefs(mParent));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!mParent) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!mParent) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// insert the new node
|
||||
result = nsEditor::SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
result = mEditor->SplitNodeImpl(mExistingRightNode, mOffset, mNewLeftNode, mParent);
|
||||
if (NS_SUCCEEDED(result) && mNewLeftNode)
|
||||
{
|
||||
// Insert formatting whitespace for the new node:
|
||||
|
@ -85,8 +85,8 @@ NS_IMETHODIMP SplitElementTxn::Do(void)
|
|||
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mNewLeftNode, mOffset);
|
||||
}
|
||||
else {
|
||||
|
@ -107,8 +107,7 @@ NS_IMETHODIMP SplitElementTxn::Undo(void)
|
|||
}
|
||||
|
||||
// this assumes Do inserted the new node in front of the prior existing node
|
||||
nsresult result;
|
||||
result = nsEditor::JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
|
||||
nsresult result = mEditor->JoinNodesImpl(mExistingRightNode, mNewLeftNode, mParent, PR_FALSE);
|
||||
if (gNoisy)
|
||||
{
|
||||
printf("** after join left child node %p into right node %p\n", mNewLeftNode.get(), mExistingRightNode.get());
|
||||
|
@ -117,14 +116,6 @@ NS_IMETHODIMP SplitElementTxn::Undo(void)
|
|||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
if (gNoisy) { printf(" left node = %p removed\n", mNewLeftNode.get()); }
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
result = selection->Collapse(mExistingRightNode, mOffset);
|
||||
}
|
||||
else {
|
||||
result = NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
0x690c6290, 0xac48, 0x11d2, \
|
||||
{0x86, 0xd8, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} }
|
||||
|
||||
class nsEditor;
|
||||
|
||||
/**
|
||||
* A transaction that splits an element E into two identical nodes, E1 and E2
|
||||
* with the children of E divided between E1 and E2.
|
||||
|
@ -50,7 +52,7 @@ public:
|
|||
* aOffset may refer to children of aNode, or content of aNode.
|
||||
* The left node will have child|content 0..aOffset-1.
|
||||
*/
|
||||
NS_IMETHOD Init (nsIEditor *aEditor,
|
||||
NS_IMETHOD Init (nsEditor *aEditor,
|
||||
nsIDOMNode *aNode,
|
||||
PRInt32 aOffset);
|
||||
protected:
|
||||
|
@ -93,7 +95,7 @@ protected:
|
|||
|
||||
/** the parent shared by mExistingRightNode and mNewLeftNode */
|
||||
nsCOMPtr<nsIDOMNode> mParent;
|
||||
nsIEditor* mEditor;
|
||||
nsEditor* mEditor;
|
||||
|
||||
friend class TransactionFactory;
|
||||
|
||||
|
|
|
@ -632,6 +632,14 @@ nsEditor::EndPlaceHolderTransaction()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsEditor::ShouldTxnSetSelection(PRBool *aResult)
|
||||
{
|
||||
if (!aResult) return NS_ERROR_NULL_POINTER;
|
||||
*aResult = mShouldTxnSetSelection;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// XXX: the rule system should tell us which node to select all on (ie, the root, or the body)
|
||||
NS_IMETHODIMP nsEditor::SelectAll()
|
||||
{
|
||||
|
@ -1743,24 +1751,24 @@ NS_IMETHODIMP nsEditor::InsertTextImpl(const nsString& aStringToInsert)
|
|||
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
EditTxn *txn;
|
||||
if (mInIMEMode)
|
||||
{
|
||||
if (!mIMETextNode)
|
||||
{
|
||||
EditTxn *txn;
|
||||
if (mInIMEMode)
|
||||
{
|
||||
if (!mIMETextNode)
|
||||
{
|
||||
mIMETextNode = nodeAsText;
|
||||
mIMETextOffset = offset;
|
||||
}
|
||||
result = CreateTxnForIMEText(aStringToInsert,(IMETextTxn**)&txn);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = CreateTxnForInsertText(aStringToInsert, nodeAsText, offset, (InsertTextTxn**)&txn);
|
||||
}
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// let listeners know whats up
|
||||
result = CreateTxnForIMEText(aStringToInsert,(IMETextTxn**)&txn);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = CreateTxnForInsertText(aStringToInsert, nodeAsText, offset, (InsertTextTxn**)&txn);
|
||||
}
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!txn) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// let listeners know whats up
|
||||
PRInt32 i;
|
||||
nsIEditActionListener *listener;
|
||||
if (mActionListeners)
|
||||
|
@ -1780,7 +1788,7 @@ NS_IMETHODIMP nsEditor::InsertTextImpl(const nsString& aStringToInsert)
|
|||
NS_IF_RELEASE(txn);
|
||||
EndUpdateViewBatch();
|
||||
|
||||
// let listeners know what happened
|
||||
// let listeners know what happened
|
||||
if (mActionListeners)
|
||||
{
|
||||
for (i = 0; i < mActionListeners->Count(); i++)
|
||||
|
@ -2024,10 +2032,11 @@ NS_IMETHODIMP nsEditor::CreateTxnForInsertText(const nsString & aStringToInsert,
|
|||
result = TransactionFactory::GetNewTransaction(InsertTextTxn::GetCID(), (EditTxn **)aTxn);
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!*aTxn) return NS_ERROR_OUT_OF_MEMORY;
|
||||
result = (*aTxn)->Init(aTextNode, aOffset, aStringToInsert, mPresShellWeak);
|
||||
result = (*aTxn)->Init(aTextNode, aOffset, aStringToInsert, this);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsEditor::DeleteText(nsIDOMCharacterData *aElement,
|
||||
PRUint32 aOffset,
|
||||
PRUint32 aLength)
|
||||
|
@ -2037,7 +2046,7 @@ NS_IMETHODIMP nsEditor::DeleteText(nsIDOMCharacterData *aElement,
|
|||
nsAutoRules beginRulesSniffing(this, kOpDeleteText, nsIEditor::ePrevious);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
// let listeners know whats up
|
||||
// let listeners know whats up
|
||||
PRInt32 i;
|
||||
nsIEditActionListener *listener;
|
||||
if (mActionListeners)
|
||||
|
@ -2052,7 +2061,7 @@ NS_IMETHODIMP nsEditor::DeleteText(nsIDOMCharacterData *aElement,
|
|||
|
||||
result = Do(txn);
|
||||
|
||||
// let listeners know what happened
|
||||
// let listeners know what happened
|
||||
if (mActionListeners)
|
||||
{
|
||||
for (i = 0; i < mActionListeners->Count(); i++)
|
||||
|
@ -2127,7 +2136,7 @@ NS_IMETHODIMP nsEditor::CreateTxnForJoinNode(nsIDOMNode *aLeftNode,
|
|||
#pragma mark -
|
||||
#endif
|
||||
|
||||
// BEGIN nsEditor public static helper methods
|
||||
// BEGIN nsEditor public helper methods
|
||||
|
||||
nsresult
|
||||
nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
||||
|
@ -2147,6 +2156,20 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
|||
(nsnull!=aNewLeftNode) &&
|
||||
(nsnull!=aParent))
|
||||
{
|
||||
// get selection
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// remember some selection points
|
||||
nsCOMPtr<nsIDOMNode> selStartNode, selEndNode;
|
||||
PRInt32 selStartOffset, selEndOffset;
|
||||
result = GetStartNodeAndOffset(selection, &selStartNode, &selStartOffset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
result = GetEndNodeAndOffset(selection, &selEndNode, &selEndOffset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
result = aParent->InsertBefore(aNewLeftNode, aExistingRightNode, getter_AddRefs(resultNode));
|
||||
//printf(" after insert\n"); content->List(); // DEBUG
|
||||
|
@ -2197,6 +2220,41 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
|
|||
}
|
||||
}
|
||||
}
|
||||
// handle selection
|
||||
if (GetShouldTxnSetSelection())
|
||||
{
|
||||
// editor wants us to set selection at split point
|
||||
selection->Collapse(aNewLeftNode, aOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
// and adjust the selection if needed
|
||||
// HACK: this is overly simplified - multi-range selections need more work than this
|
||||
if (selStartNode == aExistingRightNode)
|
||||
{
|
||||
if (selStartOffset < aOffset)
|
||||
{
|
||||
selStartNode = aNewLeftNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
selStartOffset -= aOffset;
|
||||
}
|
||||
}
|
||||
if (selEndNode == aExistingRightNode)
|
||||
{
|
||||
if (selEndOffset < aOffset)
|
||||
{
|
||||
selEndNode = aNewLeftNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
selEndOffset -= aOffset;
|
||||
}
|
||||
}
|
||||
selection->Collapse(selStartNode,selStartOffset);
|
||||
selection->Extend(selEndNode,selEndOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2213,14 +2271,28 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
|||
PRBool aNodeToKeepIsFirst)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
NS_ASSERTION(((nsnull!=aNodeToKeep) &&
|
||||
(nsnull!=aNodeToJoin) &&
|
||||
(nsnull!=aParent)),
|
||||
"null arg");
|
||||
if ((nsnull!=aNodeToKeep) &&
|
||||
(nsnull!=aNodeToJoin) &&
|
||||
(nsnull!=aParent))
|
||||
NS_ASSERTION(aNodeToKeep && aNodeToJoin && aParent, "null arg");
|
||||
if (aNodeToKeep && aNodeToJoin && aParent)
|
||||
{
|
||||
// get selection
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// remember some selection points
|
||||
nsCOMPtr<nsIDOMNode> selStartNode, selEndNode;
|
||||
PRInt32 selStartOffset, selEndOffset;
|
||||
result = GetStartNodeAndOffset(selection, &selStartNode, &selStartOffset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
result = GetEndNodeAndOffset(selection, &selEndNode, &selEndOffset);
|
||||
if (NS_FAILED(result)) return result;
|
||||
PRUint32 firstNodeLength;
|
||||
nsCOMPtr<nsIDOMNode> leftNode = aNodeToJoin;
|
||||
if (aNodeToKeepIsFirst) leftNode = aNodeToKeep;
|
||||
result = GetLengthOfDOMNode(leftNode, firstNodeLength);
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
// if it's a text node, just shuffle around some text
|
||||
nsCOMPtr<nsIDOMCharacterData> keepNodeAsText( do_QueryInterface(aNodeToKeep) );
|
||||
nsCOMPtr<nsIDOMCharacterData> joinNodeAsText( do_QueryInterface(aNodeToJoin) );
|
||||
|
@ -2249,9 +2321,9 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
|||
{
|
||||
PRInt32 i; // must be signed int!
|
||||
PRUint32 childCount=0;
|
||||
childNodes->GetLength(&childCount);
|
||||
nsCOMPtr<nsIDOMNode> firstNode; //only used if aNodeToKeepIsFirst is false
|
||||
if (PR_FALSE==aNodeToKeepIsFirst)
|
||||
childNodes->GetLength(&childCount);
|
||||
if (!aNodeToKeepIsFirst)
|
||||
{ // remember the first child in aNodeToKeep, we'll insert all the children of aNodeToJoin in front of it
|
||||
result = aNodeToKeep->GetFirstChild(getter_AddRefs(firstNode));
|
||||
// GetFirstChild returns nsnull firstNode if aNodeToKeep has no children, that's ok.
|
||||
|
@ -2265,7 +2337,7 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
|||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||
{
|
||||
if (PR_TRUE==aNodeToKeepIsFirst)
|
||||
if (aNodeToKeepIsFirst)
|
||||
{ // append children of aNodeToJoin
|
||||
//was result = aNodeToKeep->AppendChild(childNode, getter_AddRefs(resultNode));
|
||||
result = aNodeToKeep->InsertBefore(childNode, previousChild, getter_AddRefs(resultNode));
|
||||
|
@ -2288,6 +2360,35 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
|||
{ // delete the extra node
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
result = aParent->RemoveChild(aNodeToJoin, getter_AddRefs(resultNode));
|
||||
|
||||
if (GetShouldTxnSetSelection())
|
||||
{
|
||||
// editor wants us to set selection at join point
|
||||
selection->Collapse(aNodeToKeep, firstNodeLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
// and adjust the selection if needed
|
||||
// HACK: this is overly simplified - multi-range selections need more work than this
|
||||
if (selStartNode == aNodeToJoin)
|
||||
{
|
||||
selStartNode = aNodeToKeep;
|
||||
if (aNodeToKeepIsFirst)
|
||||
{
|
||||
selStartOffset += firstNodeLength;
|
||||
}
|
||||
}
|
||||
if (selEndNode == aNodeToJoin)
|
||||
{
|
||||
selEndNode = aNodeToKeep;
|
||||
if (aNodeToKeepIsFirst)
|
||||
{
|
||||
selEndOffset += firstNodeLength;
|
||||
}
|
||||
}
|
||||
selection->Collapse(selStartNode,selStartOffset);
|
||||
selection->Extend(selEndNode,selEndOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -3998,13 +4099,13 @@ nsresult nsEditor::EndUpdateViewBatch()
|
|||
{
|
||||
NS_PRECONDITION(mUpdateCount>0, "bad state");
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
nsresult rv = GetPresShell(getter_AddRefs(presShell));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
StCaretHider caretHider(presShell);
|
||||
|
||||
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
nsresult selectionResult = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(selectionResult) && selection) {
|
||||
|
@ -4028,6 +4129,18 @@ nsresult nsEditor::EndUpdateViewBatch()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEditor::GetShouldTxnSetSelection()
|
||||
{
|
||||
return mShouldTxnSetSelection;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsEditor::SetShouldTxnSetSelection(PRBool aShould)
|
||||
{
|
||||
mShouldTxnSetSelection = aShould;
|
||||
}
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
|
@ -4270,7 +4383,7 @@ nsEditor::CreateTxnForIMEText(const nsString & aStringToInsert,
|
|||
{
|
||||
NS_ASSERTION(aTxn, "illegal value- null ptr- aTxn");
|
||||
if(!aTxn) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
|
||||
nsresult result;
|
||||
|
||||
result = TransactionFactory::GetNewTransaction(IMETextTxn::GetCID(), (EditTxn **)aTxn);
|
||||
|
|
|
@ -142,6 +142,7 @@ public:
|
|||
|
||||
NS_IMETHOD BeginPlaceHolderTransaction(nsIAtom *aName);
|
||||
NS_IMETHOD EndPlaceHolderTransaction();
|
||||
NS_IMETHOD ShouldTxnSetSelection(PRBool *aResult);
|
||||
|
||||
// pure virtual, because the definition of 'empty' depends on the doc type
|
||||
NS_IMETHOD GetDocumentIsEmpty(PRBool *aDocumentIsEmpty)=0;
|
||||
|
@ -396,10 +397,10 @@ public:
|
|||
* @param aNewLeftNode [OUT] the new node resulting from the split, becomes aExistingRightNode's previous sibling.
|
||||
* @param aParent the parent of aExistingRightNode
|
||||
*/
|
||||
static nsresult SplitNodeImpl(nsIDOMNode *aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode *aNewLeftNode,
|
||||
nsIDOMNode *aParent);
|
||||
nsresult SplitNodeImpl(nsIDOMNode *aExistingRightNode,
|
||||
PRInt32 aOffset,
|
||||
nsIDOMNode *aNewLeftNode,
|
||||
nsIDOMNode *aParent);
|
||||
|
||||
/**
|
||||
* JoinNodes() takes 2 nodes and merge their content|children.
|
||||
|
@ -410,10 +411,10 @@ public:
|
|||
* @param aNodeToKeepIsFirst if PR_TRUE, the contents|children of aNodeToKeep come before the
|
||||
* contents|children of aNodeToJoin, otherwise their positions are switched.
|
||||
*/
|
||||
static nsresult JoinNodesImpl(nsIDOMNode *aNodeToKeep,
|
||||
nsIDOMNode *aNodeToJoin,
|
||||
nsIDOMNode *aParent,
|
||||
PRBool aNodeToKeepIsFirst);
|
||||
nsresult JoinNodesImpl(nsIDOMNode *aNodeToKeep,
|
||||
nsIDOMNode *aNodeToJoin,
|
||||
nsIDOMNode *aParent,
|
||||
PRBool aNodeToKeepIsFirst);
|
||||
|
||||
/**
|
||||
* Set aOffset to the offset of aChild in aParent.
|
||||
|
@ -629,6 +630,8 @@ public:
|
|||
nsresult BeginUpdateViewBatch(void);
|
||||
nsresult EndUpdateViewBatch(void);
|
||||
|
||||
PRBool GetShouldTxnSetSelection();
|
||||
void SetShouldTxnSetSelection(PRBool aShould);
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -645,7 +648,7 @@ protected:
|
|||
PRInt32 mPlaceHolderBatch; // nesting count for batching
|
||||
nsCOMPtr<nsIDOMNode> mTxnStartNode; // saved selection info to pass to placeholder at init time
|
||||
PRInt32 mTxnStartOffset; // " " " "
|
||||
|
||||
PRBool mShouldTxnSetSelection; // turn off for conservative selection adjustment by txns
|
||||
//
|
||||
// data necessary to build IME transactions
|
||||
//
|
||||
|
@ -666,6 +669,7 @@ protected:
|
|||
static PRInt32 gInstanceCount;
|
||||
|
||||
friend PRBool NSCanUnload(nsISupports* serviceMgr);
|
||||
friend class nsAutoTxnsConserveSelection;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -107,5 +107,36 @@ class nsAutoRules
|
|||
};
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* stack based helper class for turning off active selection adjustment
|
||||
* by low level transactions
|
||||
*/
|
||||
class nsAutoTxnsConserveSelection
|
||||
{
|
||||
public:
|
||||
|
||||
nsAutoTxnsConserveSelection(nsEditor *ed) : mEd(ed), mOldState(PR_TRUE)
|
||||
{
|
||||
if (mEd)
|
||||
{
|
||||
mOldState = mEd->GetShouldTxnSetSelection();
|
||||
mEd->SetShouldTxnSetSelection(PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
~nsAutoTxnsConserveSelection()
|
||||
{
|
||||
if (mEd)
|
||||
{
|
||||
mEd->SetShouldTxnSetSelection(mOldState);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
nsEditor *mEd;
|
||||
PRBool mOldState;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // nsEditorUtils_h__
|
||||
|
|
|
@ -153,6 +153,8 @@ nsHTMLEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
|||
|
||||
if (mDocChangeRange && !((action == nsEditor::kOpUndo) || (action == nsEditor::kOpRedo)))
|
||||
{
|
||||
nsAutoTxnsConserveSelection dontSpazMySelection(mEditor);
|
||||
|
||||
// expand the "changed doc range" as needed
|
||||
res = PromoteRange(mDocChangeRange, action);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
@ -2687,7 +2689,7 @@ nsHTMLEditRules::ReplaceContainer(nsIDOMNode *inNode,
|
|||
// the parent of inNode
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::RemoveContainer(nsIDOMNode *inNode)
|
||||
nsHTMLEditRules::RemoveContainer(nsIDOMNode *inNode, PRBool aAddBRIfNeeded)
|
||||
{
|
||||
if (!inNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
@ -2698,6 +2700,38 @@ nsHTMLEditRules::RemoveContainer(nsIDOMNode *inNode)
|
|||
PRInt32 offset;
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// add BR's before and/or after the inNode
|
||||
// if aAddBRIfNeeded is set and if the content
|
||||
// before/after the node is inline.
|
||||
// Only do this if inNode is a block node.
|
||||
if (aAddBRIfNeeded && mEditor->IsBlockNode(inNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> nearNode, brNode;
|
||||
res = GetPriorHTMLSibling(inNode, &nearNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nearNode && mEditor->IsInlineNode(nearNode))
|
||||
{
|
||||
res = mEditor->CreateBR(parent, offset, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// refresh location info
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
res = GetNextHTMLSibling(inNode, &nearNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nearNode && mEditor->IsInlineNode(nearNode))
|
||||
{
|
||||
res = mEditor->CreateBR(parent, offset+1, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// refresh location info
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
|
||||
// loop through the child nodes of inNode and promote them
|
||||
// into inNode's parent.
|
||||
PRBool bHasMoreChildren;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
|
@ -3249,7 +3283,7 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString
|
|||
|
||||
// we special case an empty tag name to mean "remove block parents".
|
||||
// This is used for the "normal" paragraph style in mail-compose
|
||||
if (aBlockTag->IsEmpty()) bNoParent = PR_TRUE;
|
||||
if (aBlockTag->IsEmpty() || *aBlockTag=="normal") bNoParent = PR_TRUE;
|
||||
|
||||
arrayOfNodes->Count(&listCount);
|
||||
|
||||
|
@ -3272,11 +3306,6 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString
|
|||
continue; // do nothing to this block
|
||||
}
|
||||
|
||||
// if curNode is a <pre> and we are converting to non-pre, we need
|
||||
// to process the text inside the <pre> so as to convert returns
|
||||
// to breaks, and runs of spaces to nbsps.
|
||||
// xxx floppy moose
|
||||
|
||||
// if curNode is a mozdiv, p, header, address, or pre, replace
|
||||
// it with a new block of correct type.
|
||||
// xxx floppy moose: pre cant hold everything the others can
|
||||
|
@ -3294,10 +3323,10 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString
|
|||
curBlock = 0; // forget any previous block used for previous inline nodes
|
||||
if (bNoParent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> brNode;
|
||||
res = mEditor->CreateBR(curParent, offset+1, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = RemoveContainer(curNode);
|
||||
// nsCOMPtr<nsIDOMNode> brNode;
|
||||
// res = mEditor->CreateBR(curParent, offset+1, &brNode);
|
||||
// if (NS_FAILED(res)) return res;
|
||||
res = RemoveContainer(curNode, PR_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4029,10 +4058,22 @@ nsHTMLEditRules::PopListItem(nsIDOMNode *aListItem, PRBool *aOutOfList)
|
|||
// unwrap list item contents if they are no longer in a list
|
||||
if (!IsList(curParPar) && IsListItem(curNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> mozDiv;
|
||||
nsCOMPtr<nsIDOMNode> lastChild;
|
||||
res = GetLastEditableChild(curNode, &lastChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = RemoveContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (mEditor->IsInlineNode(lastChild))
|
||||
{
|
||||
// last thing inside of the listitem wasn't a block node.
|
||||
// insert a BR to preserve the illusion of block boundaries
|
||||
nsCOMPtr<nsIDOMNode> node, brNode;
|
||||
PRInt32 offset;
|
||||
res = nsEditor::GetNodeLocation(lastChild, &node, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->CreateBR(node, offset+1, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
*aOutOfList = PR_TRUE;
|
||||
}
|
||||
return res;
|
||||
|
|
|
@ -133,7 +133,7 @@ protected:
|
|||
nsresult ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString *aBlockTag);
|
||||
|
||||
nsresult ReplaceContainer(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, const nsString &aNodeType);
|
||||
nsresult RemoveContainer(nsIDOMNode *inNode);
|
||||
nsresult RemoveContainer(nsIDOMNode *inNode, PRBool aAddBRIfNeeded=PR_FALSE);
|
||||
nsresult InsertContainerAbove(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, const nsString &aNodeType);
|
||||
|
||||
nsresult JoinNodesSmart( nsIDOMNode *aNodeLeft,
|
||||
|
|
|
@ -1818,13 +1818,9 @@ NS_IMETHODIMP nsHTMLEditor::SetParagraphFormat(const nsString& aParagraphFormat)
|
|||
//Kinda sad to waste memory just to force lower case
|
||||
nsAutoString tag = aParagraphFormat;
|
||||
tag.ToLowerCase();
|
||||
if (tag == "normal")
|
||||
{
|
||||
res = InsertBasicBlock("p");
|
||||
}
|
||||
//XXX: TODO: Do we really want to support setting list types here?
|
||||
// If yes, we need to add "dd", "dt" for <dl> support
|
||||
else if (tag == "li")
|
||||
if (tag == "li")
|
||||
{
|
||||
//XXX: Why do we assume "ul" What about "ol"? This will change an OL into a UL list!
|
||||
res = MakeOrChangeList("ul");
|
||||
|
|
|
@ -1080,9 +1080,6 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection,
|
|||
res = mEditor->JoinNodes(selectedNode, siblingNode, parentNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// selectedNode will remain after the join, siblingNode is removed
|
||||
// set selection
|
||||
res = aSelection->Collapse(siblingNode, selectedNodeLength);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
// if, after all this work, selectedNode is empty, delete it
|
||||
|
|
|
@ -212,6 +212,7 @@ public:
|
|||
|
||||
NS_IMETHOD BeginPlaceHolderTransaction(nsIAtom *aName)=0;
|
||||
NS_IMETHOD EndPlaceHolderTransaction()=0;
|
||||
NS_IMETHOD ShouldTxnSetSelection(PRBool *aResult)=0;
|
||||
|
||||
/* ------------ Clipboard methods -------------- */
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче