This commit is contained in:
jfrancis%netscape.com 2000-01-04 03:09:41 +00:00
Родитель b4b5e28fd5
Коммит d6e95890c8
35 изменённых файлов: 795 добавлений и 512 удалений

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

@ -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 -------------- */