diff --git a/mozilla/editor/base/nsEditor.cpp b/mozilla/editor/base/nsEditor.cpp index d6901118266..eee59deaf9c 100644 --- a/mozilla/editor/base/nsEditor.cpp +++ b/mozilla/editor/base/nsEditor.cpp @@ -786,6 +786,8 @@ nsEditor::nsEditor() , mEditorObservers(nsnull) , mDocDirtyState(-1) , mDocWeak(nsnull) +, mAction(nsnull) +, mDirection(eNone) { //initialize member variables here NS_INIT_REFCNT(); @@ -1096,8 +1098,6 @@ nsEditor::Undo(PRUint32 aCount) nsAutoRules beginRulesSniffing(this, kOpUndo, nsIEditor::eNone); - BeginUpdateViewBatch(); - if ((nsITransactionManager *)nsnull!=mTxnMgr.get()) { PRUint32 i=0; @@ -1113,7 +1113,6 @@ nsEditor::Undo(PRUint32 aCount) } } - EndUpdateViewBatch(); NotifyEditorObservers(); return result; } @@ -1142,7 +1141,6 @@ nsEditor::Redo(PRUint32 aCount) nsresult result = NS_OK; nsAutoRules beginRulesSniffing(this, kOpRedo, nsIEditor::eNone); - BeginUpdateViewBatch(); if ((nsITransactionManager *)nsnull!=mTxnMgr.get()) { @@ -1159,7 +1157,6 @@ nsEditor::Redo(PRUint32 aCount) } } - EndUpdateViewBatch(); NotifyEditorObservers(); return result; } @@ -1244,6 +1241,11 @@ nsEditor::EndPlaceHolderTransaction() { // time to turn off the batch EndUpdateViewBatch(); + // make sure selection is in view + nsCOMPtr selCon; + if (NS_SUCCEEDED(GetSelectionController(getter_AddRefs(selCon))) && selCon) + selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION); + if (mSelState) { // we saved the selection state, but never got to hand it to placeholder @@ -2537,15 +2539,19 @@ nsEditor::GetRootElement(nsIDOMElement **aBodyElement) NS_IMETHODIMP nsEditor::StartOperation(PRInt32 opID, nsIEditor::EDirection aDirection) { + mAction = opID; + mDirection = aDirection; return NS_OK; } /** All editor operations which alter the doc should be followed - * with a call to EndOperation, naming the action and direction */ + * with a call to EndOperation */ NS_IMETHODIMP -nsEditor::EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection) +nsEditor::EndOperation() { + mAction = nsnull; + mDirection = eNone; return NS_OK; } @@ -5248,7 +5254,7 @@ nsEditor::SetShouldTxnSetSelection(PRBool aShould) NS_IMETHODIMP -nsEditor::DeleteSelectionImpl(EDirection aAction) +nsEditor::DeleteSelectionImpl(nsIEditor::EDirection aAction) { nsresult res; diff --git a/mozilla/editor/base/nsEditor.h b/mozilla/editor/base/nsEditor.h index ca3c148c34e..45c54565e67 100644 --- a/mozilla/editor/base/nsEditor.h +++ b/mozilla/editor/base/nsEditor.h @@ -480,8 +480,8 @@ public: NS_IMETHOD StartOperation(PRInt32 opID, nsIEditor::EDirection aDirection); /** All editor operations which alter the doc should be followed - * with a call to EndOperation, naming the action and direction */ - NS_IMETHOD EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection); + * with a call to EndOperation */ + NS_IMETHOD EndOperation(); /** return the string that represents text nodes in the content tree */ static nsresult GetTextNodeTag(nsString& aOutString); @@ -755,15 +755,17 @@ protected: nsSelectionState *mSavedSel; // cached selection for nsAutoSelectionReset PRBool mShouldTxnSetSelection; // turn off for conservative selection adjustment by txns nsCOMPtr mBodyElement; // cached body node - // + PRInt32 mAction; // the current editor action + EDirection mDirection; // the current direction of editor action + // data necessary to build IME transactions - // PRBool mInIMEMode; // are we inside an IME composition? nsIPrivateTextRangeList* mIMETextRangeList; // IME special selection ranges nsCOMPtr mIMETextNode; // current IME text node PRUint32 mIMETextOffset; // offset in text node where IME comp string begins PRUint32 mIMEBufferLength; // current length of IME comp string + // various listeners nsVoidArray* mActionListeners; // listens to all low level actions on the doc nsVoidArray* mEditorObservers; // just notify once per high level change nsCOMPtr mDocStateListeners;// listen to overall doc state (dirty or not, just created, etc) @@ -777,6 +779,7 @@ protected: friend PRBool NSCanUnload(nsISupports* serviceMgr); friend class nsAutoTxnsConserveSelection; friend class nsAutoSelectionReset; + friend class nsAutoRules; }; diff --git a/mozilla/editor/base/nsEditorUtils.h b/mozilla/editor/base/nsEditorUtils.h index 1e1c41e4189..d5fc7a2a69d 100644 --- a/mozilla/editor/base/nsEditorUtils.h +++ b/mozilla/editor/base/nsEditorUtils.h @@ -87,14 +87,25 @@ class nsAutoRules public: nsAutoRules(nsEditor *ed, PRInt32 action, nsIEditor::EDirection aDirection) : - mEd(ed), mAction(action), mDirection(aDirection) - {if (mEd) mEd->StartOperation(mAction, mDirection);} - ~nsAutoRules() {if (mEd) mEd->EndOperation(mAction, mDirection);} + mEd(ed), mDoNothing(PR_FALSE) + { + if (mEd && !mEd->mAction) // mAction will already be set if this is nested call + { + mEd->StartOperation(action, aDirection); + } + else mDoNothing = PR_TRUE; // nested calls will end up here + } + ~nsAutoRules() + { + if (mEd && !mDoNothing) + { + mEd->EndOperation(); + } + } protected: nsEditor *mEd; - PRInt32 mAction; - nsIEditor::EDirection mDirection; + PRBool mDoNothing; }; diff --git a/mozilla/editor/base/nsHTMLEditor.cpp b/mozilla/editor/base/nsHTMLEditor.cpp index 730419255c2..67554518b3d 100644 --- a/mozilla/editor/base/nsHTMLEditor.cpp +++ b/mozilla/editor/base/nsHTMLEditor.cpp @@ -4503,7 +4503,7 @@ nsHTMLEditor::Undo(PRUint32 aCount) ForceCompositionEnd(); nsresult result = NS_OK; - BeginUpdateViewBatch(); + nsAutoRules beginRulesSniffing(this, kOpUndo, nsIEditor::eNone); nsTextRulesInfo ruleInfo(nsTextEditRules::kUndo); nsCOMPtr selection; @@ -4517,8 +4517,6 @@ nsHTMLEditor::Undo(PRUint32 aCount) result = mRules->DidDoAction(selection, &ruleInfo, result); } - EndUpdateViewBatch(); - return result; } @@ -4528,7 +4526,7 @@ nsHTMLEditor::Redo(PRUint32 aCount) { nsresult result = NS_OK; - BeginUpdateViewBatch(); + nsAutoRules beginRulesSniffing(this, kOpRedo, nsIEditor::eNone); nsTextRulesInfo ruleInfo(nsTextEditRules::kRedo); nsCOMPtr selection; @@ -4542,8 +4540,6 @@ nsHTMLEditor::Redo(PRUint32 aCount) result = mRules->DidDoAction(selection, &ruleInfo, result); } - EndUpdateViewBatch(); - return result; } @@ -5906,23 +5902,27 @@ void nsHTMLEditor::ApplyStyleSheetToPresShellDocument(nsICSSStyleSheet* aSheet, NS_IMETHODIMP nsHTMLEditor::StartOperation(PRInt32 opID, nsIEditor::EDirection aDirection) { - if (! ((opID==kOpInsertText) || (opID==kOpInsertIMEText)) ) + nsEditor::StartOperation(opID, aDirection); // will set mAction, mDirection + if (! ((mAction==kOpInsertText) || (mAction==kOpInsertIMEText)) ) ClearInlineStylesCache(); - if (mRules) return mRules->BeforeEdit(opID, aDirection); + if (mRules) return mRules->BeforeEdit(mAction, mDirection); return NS_OK; } /** All editor operations which alter the doc should be followed - * with a call to EndOperation, naming the action and direction */ + * with a call to EndOperation */ NS_IMETHODIMP -nsHTMLEditor::EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection) +nsHTMLEditor::EndOperation() { - if (! ((opID==kOpInsertText) || (opID==kOpInsertIMEText)) ) + // post processing + if (! ((mAction==kOpInsertText) || (mAction==kOpInsertIMEText) || (mAction==kOpIgnore)) ) ClearInlineStylesCache(); - if (mRules) return mRules->AfterEdit(opID, aDirection); - return NS_OK; -} + nsresult res = NS_OK; + if (mRules) res = mRules->AfterEdit(mAction, mDirection); + nsEditor::EndOperation(); // will clear mAction, mDirection + return res; +} PRBool diff --git a/mozilla/editor/base/nsHTMLEditor.h b/mozilla/editor/base/nsHTMLEditor.h index 95f10f9edcf..cd5fc5913a3 100644 --- a/mozilla/editor/base/nsHTMLEditor.h +++ b/mozilla/editor/base/nsHTMLEditor.h @@ -288,8 +288,8 @@ public: NS_IMETHOD StartOperation(PRInt32 opID, nsIEditor::EDirection aDirection); /** All editor operations which alter the doc should be followed - * with a call to EndOperation, naming the action and direction */ - NS_IMETHOD EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection); + * with a call to EndOperation */ + NS_IMETHOD EndOperation(); /** returns PR_TRUE if aParentTag can contain a child of type aChildTag */ virtual PRBool TagCanContainTag(const nsString &aParentTag, const nsString &aChildTag); @@ -496,7 +496,7 @@ protected: /* small utility routine to test the eEditorReadonly bit */ PRBool IsModifiable(); - + /* helpers for block transformations */ nsresult MakeDefinitionItem(const nsString& aItemType); nsresult InsertBasicBlock(const nsString& aBlockType); diff --git a/mozilla/editor/libeditor/base/nsEditor.cpp b/mozilla/editor/libeditor/base/nsEditor.cpp index d6901118266..eee59deaf9c 100644 --- a/mozilla/editor/libeditor/base/nsEditor.cpp +++ b/mozilla/editor/libeditor/base/nsEditor.cpp @@ -786,6 +786,8 @@ nsEditor::nsEditor() , mEditorObservers(nsnull) , mDocDirtyState(-1) , mDocWeak(nsnull) +, mAction(nsnull) +, mDirection(eNone) { //initialize member variables here NS_INIT_REFCNT(); @@ -1096,8 +1098,6 @@ nsEditor::Undo(PRUint32 aCount) nsAutoRules beginRulesSniffing(this, kOpUndo, nsIEditor::eNone); - BeginUpdateViewBatch(); - if ((nsITransactionManager *)nsnull!=mTxnMgr.get()) { PRUint32 i=0; @@ -1113,7 +1113,6 @@ nsEditor::Undo(PRUint32 aCount) } } - EndUpdateViewBatch(); NotifyEditorObservers(); return result; } @@ -1142,7 +1141,6 @@ nsEditor::Redo(PRUint32 aCount) nsresult result = NS_OK; nsAutoRules beginRulesSniffing(this, kOpRedo, nsIEditor::eNone); - BeginUpdateViewBatch(); if ((nsITransactionManager *)nsnull!=mTxnMgr.get()) { @@ -1159,7 +1157,6 @@ nsEditor::Redo(PRUint32 aCount) } } - EndUpdateViewBatch(); NotifyEditorObservers(); return result; } @@ -1244,6 +1241,11 @@ nsEditor::EndPlaceHolderTransaction() { // time to turn off the batch EndUpdateViewBatch(); + // make sure selection is in view + nsCOMPtr selCon; + if (NS_SUCCEEDED(GetSelectionController(getter_AddRefs(selCon))) && selCon) + selCon->ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL, nsISelectionController::SELECTION_FOCUS_REGION); + if (mSelState) { // we saved the selection state, but never got to hand it to placeholder @@ -2537,15 +2539,19 @@ nsEditor::GetRootElement(nsIDOMElement **aBodyElement) NS_IMETHODIMP nsEditor::StartOperation(PRInt32 opID, nsIEditor::EDirection aDirection) { + mAction = opID; + mDirection = aDirection; return NS_OK; } /** All editor operations which alter the doc should be followed - * with a call to EndOperation, naming the action and direction */ + * with a call to EndOperation */ NS_IMETHODIMP -nsEditor::EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection) +nsEditor::EndOperation() { + mAction = nsnull; + mDirection = eNone; return NS_OK; } @@ -5248,7 +5254,7 @@ nsEditor::SetShouldTxnSetSelection(PRBool aShould) NS_IMETHODIMP -nsEditor::DeleteSelectionImpl(EDirection aAction) +nsEditor::DeleteSelectionImpl(nsIEditor::EDirection aAction) { nsresult res; diff --git a/mozilla/editor/libeditor/base/nsEditor.h b/mozilla/editor/libeditor/base/nsEditor.h index ca3c148c34e..45c54565e67 100644 --- a/mozilla/editor/libeditor/base/nsEditor.h +++ b/mozilla/editor/libeditor/base/nsEditor.h @@ -480,8 +480,8 @@ public: NS_IMETHOD StartOperation(PRInt32 opID, nsIEditor::EDirection aDirection); /** All editor operations which alter the doc should be followed - * with a call to EndOperation, naming the action and direction */ - NS_IMETHOD EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection); + * with a call to EndOperation */ + NS_IMETHOD EndOperation(); /** return the string that represents text nodes in the content tree */ static nsresult GetTextNodeTag(nsString& aOutString); @@ -755,15 +755,17 @@ protected: nsSelectionState *mSavedSel; // cached selection for nsAutoSelectionReset PRBool mShouldTxnSetSelection; // turn off for conservative selection adjustment by txns nsCOMPtr mBodyElement; // cached body node - // + PRInt32 mAction; // the current editor action + EDirection mDirection; // the current direction of editor action + // data necessary to build IME transactions - // PRBool mInIMEMode; // are we inside an IME composition? nsIPrivateTextRangeList* mIMETextRangeList; // IME special selection ranges nsCOMPtr mIMETextNode; // current IME text node PRUint32 mIMETextOffset; // offset in text node where IME comp string begins PRUint32 mIMEBufferLength; // current length of IME comp string + // various listeners nsVoidArray* mActionListeners; // listens to all low level actions on the doc nsVoidArray* mEditorObservers; // just notify once per high level change nsCOMPtr mDocStateListeners;// listen to overall doc state (dirty or not, just created, etc) @@ -777,6 +779,7 @@ protected: friend PRBool NSCanUnload(nsISupports* serviceMgr); friend class nsAutoTxnsConserveSelection; friend class nsAutoSelectionReset; + friend class nsAutoRules; }; diff --git a/mozilla/editor/libeditor/base/nsEditorUtils.h b/mozilla/editor/libeditor/base/nsEditorUtils.h index 1e1c41e4189..d5fc7a2a69d 100644 --- a/mozilla/editor/libeditor/base/nsEditorUtils.h +++ b/mozilla/editor/libeditor/base/nsEditorUtils.h @@ -87,14 +87,25 @@ class nsAutoRules public: nsAutoRules(nsEditor *ed, PRInt32 action, nsIEditor::EDirection aDirection) : - mEd(ed), mAction(action), mDirection(aDirection) - {if (mEd) mEd->StartOperation(mAction, mDirection);} - ~nsAutoRules() {if (mEd) mEd->EndOperation(mAction, mDirection);} + mEd(ed), mDoNothing(PR_FALSE) + { + if (mEd && !mEd->mAction) // mAction will already be set if this is nested call + { + mEd->StartOperation(action, aDirection); + } + else mDoNothing = PR_TRUE; // nested calls will end up here + } + ~nsAutoRules() + { + if (mEd && !mDoNothing) + { + mEd->EndOperation(); + } + } protected: nsEditor *mEd; - PRInt32 mAction; - nsIEditor::EDirection mDirection; + PRBool mDoNothing; }; diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp index 730419255c2..67554518b3d 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp @@ -4503,7 +4503,7 @@ nsHTMLEditor::Undo(PRUint32 aCount) ForceCompositionEnd(); nsresult result = NS_OK; - BeginUpdateViewBatch(); + nsAutoRules beginRulesSniffing(this, kOpUndo, nsIEditor::eNone); nsTextRulesInfo ruleInfo(nsTextEditRules::kUndo); nsCOMPtr selection; @@ -4517,8 +4517,6 @@ nsHTMLEditor::Undo(PRUint32 aCount) result = mRules->DidDoAction(selection, &ruleInfo, result); } - EndUpdateViewBatch(); - return result; } @@ -4528,7 +4526,7 @@ nsHTMLEditor::Redo(PRUint32 aCount) { nsresult result = NS_OK; - BeginUpdateViewBatch(); + nsAutoRules beginRulesSniffing(this, kOpRedo, nsIEditor::eNone); nsTextRulesInfo ruleInfo(nsTextEditRules::kRedo); nsCOMPtr selection; @@ -4542,8 +4540,6 @@ nsHTMLEditor::Redo(PRUint32 aCount) result = mRules->DidDoAction(selection, &ruleInfo, result); } - EndUpdateViewBatch(); - return result; } @@ -5906,23 +5902,27 @@ void nsHTMLEditor::ApplyStyleSheetToPresShellDocument(nsICSSStyleSheet* aSheet, NS_IMETHODIMP nsHTMLEditor::StartOperation(PRInt32 opID, nsIEditor::EDirection aDirection) { - if (! ((opID==kOpInsertText) || (opID==kOpInsertIMEText)) ) + nsEditor::StartOperation(opID, aDirection); // will set mAction, mDirection + if (! ((mAction==kOpInsertText) || (mAction==kOpInsertIMEText)) ) ClearInlineStylesCache(); - if (mRules) return mRules->BeforeEdit(opID, aDirection); + if (mRules) return mRules->BeforeEdit(mAction, mDirection); return NS_OK; } /** All editor operations which alter the doc should be followed - * with a call to EndOperation, naming the action and direction */ + * with a call to EndOperation */ NS_IMETHODIMP -nsHTMLEditor::EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection) +nsHTMLEditor::EndOperation() { - if (! ((opID==kOpInsertText) || (opID==kOpInsertIMEText)) ) + // post processing + if (! ((mAction==kOpInsertText) || (mAction==kOpInsertIMEText) || (mAction==kOpIgnore)) ) ClearInlineStylesCache(); - if (mRules) return mRules->AfterEdit(opID, aDirection); - return NS_OK; -} + nsresult res = NS_OK; + if (mRules) res = mRules->AfterEdit(mAction, mDirection); + nsEditor::EndOperation(); // will clear mAction, mDirection + return res; +} PRBool diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.h b/mozilla/editor/libeditor/html/nsHTMLEditor.h index 95f10f9edcf..cd5fc5913a3 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.h +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.h @@ -288,8 +288,8 @@ public: NS_IMETHOD StartOperation(PRInt32 opID, nsIEditor::EDirection aDirection); /** All editor operations which alter the doc should be followed - * with a call to EndOperation, naming the action and direction */ - NS_IMETHOD EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection); + * with a call to EndOperation */ + NS_IMETHOD EndOperation(); /** returns PR_TRUE if aParentTag can contain a child of type aChildTag */ virtual PRBool TagCanContainTag(const nsString &aParentTag, const nsString &aChildTag); @@ -496,7 +496,7 @@ protected: /* small utility routine to test the eEditorReadonly bit */ PRBool IsModifiable(); - + /* helpers for block transformations */ nsresult MakeDefinitionItem(const nsString& aItemType); nsresult InsertBasicBlock(const nsString& aBlockType);