From bb138b3c5cc5c6d73e9ba91495dfeee48c184b43 Mon Sep 17 00:00:00 2001 From: "jfrancis%netscape.com" Date: Tue, 26 Oct 1999 18:54:47 +0000 Subject: [PATCH] reworking editor IME supoprt; r=kin; bugs: 13576, 11878, 11994, 13494, 16432 git-svn-id: svn://10.0.0.236/trunk@51859 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/editor/base/IMETextTxn.cpp | 67 +-- mozilla/editor/base/IMETextTxn.h | 1 - mozilla/editor/base/PlaceholderTxn.cpp | 56 ++- mozilla/editor/base/PlaceholderTxn.h | 14 +- mozilla/editor/base/TransactionFactory.cpp | 3 - mozilla/editor/base/nsEditor.cpp | 428 ++++++------------ mozilla/editor/base/nsEditor.h | 15 +- mozilla/editor/base/nsHTMLEditor.cpp | 24 +- mozilla/editor/base/nsHTMLEditor.h | 1 + mozilla/editor/base/nsIAbsorbingTransaction.h | 2 + mozilla/editor/libeditor/base/IMETextTxn.cpp | 67 +-- mozilla/editor/libeditor/base/IMETextTxn.h | 1 - .../editor/libeditor/base/PlaceholderTxn.cpp | 56 ++- .../editor/libeditor/base/PlaceholderTxn.h | 14 +- .../libeditor/base/TransactionFactory.cpp | 3 - mozilla/editor/libeditor/base/nsEditor.cpp | 428 ++++++------------ mozilla/editor/libeditor/base/nsEditor.h | 15 +- .../libeditor/base/nsIAbsorbingTransaction.h | 2 + .../editor/libeditor/html/nsHTMLEditor.cpp | 24 +- mozilla/editor/libeditor/html/nsHTMLEditor.h | 1 + 20 files changed, 474 insertions(+), 748 deletions(-) diff --git a/mozilla/editor/base/IMETextTxn.cpp b/mozilla/editor/base/IMETextTxn.cpp index 3d9982c0275..26c3fdf8671 100644 --- a/mozilla/editor/base/IMETextTxn.cpp +++ b/mozilla/editor/base/IMETextTxn.cpp @@ -17,7 +17,6 @@ */ #include "IMETextTxn.h" -#include "IMECommitTxn.h" #include "nsEditor.h" #include "nsIDOMCharacterData.h" #include "nsIPrivateTextRange.h" @@ -176,23 +175,6 @@ NS_IMETHODIMP IMETextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction) return NS_OK; } - // - // second possible case is that we have a commit transaction - // - IMECommitTxn* commitTxn = nsnull; - result = aTransaction->QueryInterface(IMECommitTxn::GetCID(),(void**)&commitTxn); - if (commitTxn && NS_SUCCEEDED(NS_OK)) - { - (void)CollapseTextSelectionOnCommit(); - mFixed = PR_TRUE; - *aDidMerge = PR_TRUE; // absorbe the commit transaction -#ifdef DEBUG_TAGUE - printf("IMETextTxn assimilated IMECommitTxn%p\n", aTransaction); -#endif - NS_RELEASE(commitTxn); - return NS_OK; - } - *aDidMerge = PR_FALSE; return NS_OK; } @@ -292,26 +274,29 @@ NS_IMETHODIMP IMETextTxn::CollapseTextSelection(void) #endif // - // run through the text range list + // run through the text range list, if any // - result = mRangeList->GetLength(&textRangeListLength); - if (NS_SUCCEEDED(result)) + if (mRangeList) { - for(i=0;iItem(i,&textRange); - if (NS_SUCCEEDED(result)) - { - result = textRange->GetRangeType(&textRangeType); - if (textRangeType==nsIPrivateTextRange::TEXTRANGE_SELECTEDCONVERTEDTEXT) + result = mRangeList->GetLength(&textRangeListLength); + if (NS_SUCCEEDED(result)) + { + for(i=0;iItem(i,&textRange); + if (NS_SUCCEEDED(result)) { - haveSelectedRange = PR_TRUE; - textRange->GetRangeStart(&selectionStart); - textRange->GetRangeEnd(&selectionEnd); - } - if (textRangeType==nsIPrivateTextRange::TEXTRANGE_CARETPOSITION) - { - haveCaretPosition = PR_TRUE; - textRange->GetRangeStart(&caretPosition); + result = textRange->GetRangeType(&textRangeType); + if (textRangeType==nsIPrivateTextRange::TEXTRANGE_SELECTEDCONVERTEDTEXT) + { + haveSelectedRange = PR_TRUE; + textRange->GetRangeStart(&selectionStart); + textRange->GetRangeEnd(&selectionEnd); + } + if (textRangeType==nsIPrivateTextRange::TEXTRANGE_CARETPOSITION) + { + haveCaretPosition = PR_TRUE; + textRange->GetRangeStart(&caretPosition); + } } } } @@ -336,15 +321,3 @@ NS_IMETHODIMP IMETextTxn::CollapseTextSelection(void) return result; } -NS_IMETHODIMP IMETextTxn::CollapseTextSelectionOnCommit(void) -{ - nsCOMPtr selection; - nsCOMPtr ps = do_QueryReferent(mPresShellWeak); - if (!ps) return NS_ERROR_NOT_INITIALIZED; - nsresult result = ps->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection)); - if (NS_SUCCEEDED(result) && selection){ - result = selection->Collapse(mElement,mOffset+mStringToInsert.Length()); - } - - return result; -} diff --git a/mozilla/editor/base/IMETextTxn.h b/mozilla/editor/base/IMETextTxn.h index 2d965ddbdf7..f9cfe79af1b 100644 --- a/mozilla/editor/base/IMETextTxn.h +++ b/mozilla/editor/base/IMETextTxn.h @@ -101,7 +101,6 @@ public: protected: NS_IMETHOD CollapseTextSelection(void); - NS_IMETHOD CollapseTextSelectionOnCommit(void); /** the text element to operate upon */ nsCOMPtr mElement; diff --git a/mozilla/editor/base/PlaceholderTxn.cpp b/mozilla/editor/base/PlaceholderTxn.cpp index aea752cfa5d..8625e0e4b64 100644 --- a/mozilla/editor/base/PlaceholderTxn.cpp +++ b/mozilla/editor/base/PlaceholderTxn.cpp @@ -20,6 +20,7 @@ #include "nsVoidArray.h" #include "nsHTMLEditor.h" #include "nsIPresShell.h" +#include "IMETextTxn.h" #if defined(NS_DEBUG) && defined(DEBUG_buster) static PRBool gNoisy = PR_TRUE; @@ -31,7 +32,9 @@ static const PRBool gNoisy = PR_FALSE; PlaceholderTxn::PlaceholderTxn() : EditAggregateTxn(), mPresShellWeak(nsnull), mAbsorb(PR_TRUE), - mForwarding(nsnull) + mForwarding(nsnull), + mIMETextTxn(nsnull), + mCommitted(PR_FALSE) { SetTransactionDescriptionID( kTransactionID ); /* log description initialized in parent constructor */ @@ -97,7 +100,7 @@ NS_IMETHODIMP PlaceholderTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransact *aDidMerge=PR_FALSE; nsresult res = NS_OK; - + if (mForwarding) { NS_NOTREACHED("tried to merge into a placeholder that was in forwarding mode!"); @@ -107,14 +110,45 @@ NS_IMETHODIMP PlaceholderTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransact EditTxn *editTxn = (EditTxn*)aTransaction; //XXX: hack, not safe! need nsIEditTransaction! if (PR_TRUE==mAbsorb) { // yep, it's one of ours. Assimilate it. - AppendChild(editTxn); + IMETextTxn* otherTxn = nsnull; + if (NS_SUCCEEDED(aTransaction->QueryInterface(IMETextTxn::GetCID(),(void**)&otherTxn)) && otherTxn) + { + // special handling for IMETextTxn's: they need to merge with any previous + // IMETextTxn in this placeholder, if possible. + if (!mIMETextTxn) + { + // this is the first IME txn in the placeholder + mIMETextTxn =otherTxn; + AppendChild(editTxn); + } + else + { + PRBool didMerge; + mIMETextTxn->Merge(&didMerge, otherTxn); + if (!didMerge) + { + // it wouldn't merge. Earlier IME txn is already commited and will + // not absorb frther IME txns. So just stack this one after it + // and remember it as a candidate for furthre merges. + mIMETextTxn =otherTxn; + AppendChild(editTxn); + } + } + NS_IF_RELEASE(otherTxn); + } + else + { + AppendChild(editTxn); + } *aDidMerge = PR_TRUE; if (gNoisy) { printf("Placeholder txn assimilated %p\n", aTransaction); } } else - { // merge typing or deletion transactions if the selection matches - if ( (mName.get() == nsHTMLEditor::gTypingTxnName) || - (mName.get() == nsHTMLEditor::gDeleteTxnName) ) + { // merge typing or IME or deletion transactions if the selection matches + if (((mName.get() == nsHTMLEditor::gTypingTxnName) || + (mName.get() == nsHTMLEditor::gIMETxnName) || + (mName.get() == nsHTMLEditor::gDeleteTxnName)) + && !mCommitted ) { nsCOMPtr plcTxn;// = do_QueryInterface(editTxn); // cant do_QueryInterface() above due to our broken transaction interfaces. @@ -139,6 +173,7 @@ NS_IMETHODIMP PlaceholderTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransact *aDidMerge = PR_TRUE; } } + NS_IF_RELEASE(atom); } } } @@ -168,8 +203,9 @@ NS_IMETHODIMP PlaceholderTxn::EndPlaceHolderBatch() if (plcTxn) plcTxn->EndPlaceHolderBatch(); } - // if we are a typing or deleting transaction, remember our selection state + // if we are a typing or IME or deleting transaction, remember our selection state if ( (mName.get() == nsHTMLEditor::gTypingTxnName) || + (mName.get() == nsHTMLEditor::gIMETxnName) || (mName.get() == nsHTMLEditor::gDeleteTxnName) ) { nsCOMPtr ps = do_QueryReferent(mPresShellWeak); @@ -190,7 +226,11 @@ NS_IMETHODIMP PlaceholderTxn::ForwardEndBatchTo(nsIAbsorbingTransaction *aForwar return NS_OK; } - +NS_IMETHODIMP PlaceholderTxn::Commit() +{ + mCommitted = PR_TRUE; + return NS_OK; +} diff --git a/mozilla/editor/base/PlaceholderTxn.h b/mozilla/editor/base/PlaceholderTxn.h index 5ad13ec7d02..56cc01677f2 100644 --- a/mozilla/editor/base/PlaceholderTxn.h +++ b/mozilla/editor/base/PlaceholderTxn.h @@ -32,6 +32,7 @@ {0x86, 0xde, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} } class nsHTMLEditor; +class IMETextTxn; /** * An aggregate transaction that knows how to absorb all subsequent @@ -77,6 +78,8 @@ public: NS_IMETHOD ForwardEndBatchTo(nsIAbsorbingTransaction *aForwardingAddress); + NS_IMETHOD Commit(); + friend class TransactionFactory; enum { kTransactionID = 11260 }; @@ -84,11 +87,14 @@ public: protected: /** the presentation shell, which we'll need to get the selection */ - nsWeakPtr mPresShellWeak; // weak reference to the nsIPresShell - PRBool mAbsorb; + nsWeakPtr mPresShellWeak; // weak reference to the nsIPresShell + PRBool mAbsorb; // do we auto absorb any and all transaction? nsCOMPtr mStartNode, mEndNode; // selection nodes at beginning and end of operation - PRInt32 mStartOffset, mEndOffset; // selection offsets at beginning and end of operation - nsWeakPtr mForwarding; + PRInt32 mStartOffset, mEndOffset; // selection offsets at beginning and end of operation + nsWeakPtr mForwarding; + IMETextTxn *mIMETextTxn; // first IME txn in this placeholder - used for IME merging + // non-owning for now - cant nsCOMPtr it due to broken transaction interfaces + PRBool mCommitted; // do we stop auto absorbing any matching placeholder txns? }; diff --git a/mozilla/editor/base/TransactionFactory.cpp b/mozilla/editor/base/TransactionFactory.cpp index c9ff0cf8336..d4b04734517 100644 --- a/mozilla/editor/base/TransactionFactory.cpp +++ b/mozilla/editor/base/TransactionFactory.cpp @@ -31,7 +31,6 @@ #include "JoinElementTxn.h" #include "nsStyleSheetTxns.h" #include "IMETextTxn.h" -#include "IMECommitTxn.h" TransactionFactory::TransactionFactory() { @@ -68,8 +67,6 @@ TransactionFactory::GetNewTransaction(REFNSIID aTxnType, EditTxn **aResult) *aResult = new EditAggregateTxn(); else if (aTxnType.Equals(IMETextTxn::GetCID())) *aResult = new IMETextTxn(); - else if (aTxnType.Equals(IMECommitTxn::GetCID())) - *aResult = new IMECommitTxn(); else if (aTxnType.Equals(AddStyleSheetTxn::GetCID())) *aResult = new AddStyleSheetTxn(); else if (aTxnType.Equals(RemoveStyleSheetTxn::GetCID())) diff --git a/mozilla/editor/base/nsEditor.cpp b/mozilla/editor/base/nsEditor.cpp index bf7ca0ab95e..cd4560373ee 100644 --- a/mozilla/editor/base/nsEditor.cpp +++ b/mozilla/editor/base/nsEditor.cpp @@ -84,7 +84,6 @@ #include "JoinElementTxn.h" #include "nsStyleSheetTxns.h" #include "IMETextTxn.h" -#include "IMECommitTxn.h" // #define HACK_FORCE_REDRAW 1 @@ -151,6 +150,11 @@ nsEditor::nsEditor() , mPlaceHolderBatch(0) , mTxnStartNode(nsnull) , mTxnStartOffset(0) +, mInIMEMode(PR_FALSE) +, mIMETextRangeList(nsnull) +, mIMETextNode(nsnull) +, mIMETextOffset(0) +, mIMEBufferLength(0) , mActionListeners(nsnull) , mDocDirtyState(-1) , mDocWeak(nsnull) @@ -184,8 +188,7 @@ nsEditor::~nsEditor() /* shut down all classes that needed initialization */ InsertTextTxn::ClassShutdown(); IMETextTxn::ClassShutdown(); - IMECommitTxn::ClassShutdown(); - + PR_AtomicDecrement(&gInstanceCount); } @@ -269,7 +272,6 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell, PRUint32 aFlags) /* initalize IME stuff */ IMETextTxn::ClassInit(); - IMECommitTxn::ClassInit(); mIMETextNode = do_QueryInterface(nsnull); mIMETextOffset = 0; mIMEBufferLength = 0; @@ -712,7 +714,7 @@ NS_IMETHODIMP nsEditor::EndOfDocument() result = nodeList->Item(0, getter_AddRefs(bodyNode)); if ((NS_SUCCEEDED(result)) && bodyNode) { - nsCOMPtr lastChild; // = GetDeepLastChild(bodyNode); + nsCOMPtr lastChild; // = GetDeepLastChild(bodyNode); result = GetLastEditableNode(bodyNode, getter_AddRefs(lastChild)); if ((NS_SUCCEEDED(result)) && lastChild) { @@ -1321,8 +1323,6 @@ nsEditor::DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed) // // The BeingComposition method is called from the Editor Composition event listeners. -// It caches the current text node and offset which is subsequently used for the -// created of IMETextTxn's. // NS_IMETHODIMP nsEditor::BeginComposition(nsTextEventReply* aReply) @@ -1331,7 +1331,6 @@ nsEditor::BeginComposition(nsTextEventReply* aReply) printf("nsEditor::StartComposition\n"); #endif nsresult result; - PRInt32 offset; nsCOMPtr selection; nsCOMPtr nodeAsText; nsCOMPtr caretP; @@ -1344,52 +1343,8 @@ nsEditor::BeginComposition(nsTextEventReply* aReply) caretP->GetWindowRelativeCoordinates(aReply->mCursorPosition,aReply->mCursorIsCollapsed); } } - result = ps->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) - { - result = NS_ERROR_UNEXPECTED; - nsCOMPtr enumerator; - result = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) - { - enumerator->First(); - nsCOMPtr currentItem; - result = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(result)) && (currentItem)) - { - result = NS_ERROR_UNEXPECTED; - nsCOMPtr range(do_QueryInterface(currentItem)); - if (range) - { - nsCOMPtr node; - result = range->GetStartParent(getter_AddRefs(node)); - if ((NS_SUCCEEDED(result)) && (node)) - { - nodeAsText = do_QueryInterface(node); - NS_ASSERTION(nodeAsText, "cannot get Text Node"); - range->GetStartOffset(&offset); - if (!nodeAsText) { - result = NS_ERROR_EDITOR_NO_TEXTNODE; - } - } - } - } - else - { - result = NS_ERROR_EDITOR_NO_SELECTION; - } - } - } - if (NS_SUCCEEDED(result) && nodeAsText) - { - // - // store the information needed to construct IME transactions for this composition - // - mIMETextNode = nodeAsText; - mIMETextOffset = offset; - mIMEBufferLength = 0; - } + mInIMEMode = PR_TRUE; return result; } @@ -1397,20 +1352,20 @@ nsEditor::BeginComposition(nsTextEventReply* aReply) NS_IMETHODIMP nsEditor::EndComposition(void) { - nsresult result; - IMECommitTxn *commitTxn; + if (!mInIMEMode) return NS_OK; // nothing to do - // - // create the commit transaction..we can do it directly from the transaction mgr - // - result = TransactionFactory::GetNewTransaction(IMECommitTxn::GetCID(), (EditTxn**)&commitTxn); - if (NS_SUCCEEDED(result) && commitTxn!=nsnull) + nsresult result; + + // commit the IME transaction..we can get at it via the transaction mgr. + // Note that this means IME won't work without an undo stack! + if (mTxnMgr) { - result = commitTxn->Init(); - NS_ASSERTION(NS_SUCCEEDED(result), "commitTxt->Init failed"); - if(NS_SUCCEEDED(result)) { - result = Do(commitTxn); - NS_ASSERTION(NS_SUCCEEDED(result), "nsEditor::Do failed"); + nsCOMPtr txn; + result = mTxnMgr->PeekUndoStack(getter_AddRefs(txn)); + nsCOMPtr plcTxn = do_QueryInterface(txn); + if (plcTxn) + { + result = plcTxn->Commit(); } } @@ -1418,6 +1373,7 @@ nsEditor::EndComposition(void) mIMETextNode = do_QueryInterface(nsnull); mIMETextOffset = 0; mIMEBufferLength = 0; + mInIMEMode = PR_FALSE; return result; } @@ -1425,25 +1381,7 @@ nsEditor::EndComposition(void) NS_IMETHODIMP nsEditor::SetCompositionString(const nsString& aCompositionString, nsIPrivateTextRangeList* aTextRangeList,nsTextEventReply* aReply) { - NS_ASSERTION(aTextRangeList, "null ptr- aTextRangeList"); - NS_ASSERTION(aReply, "null ptr- aReply"); - if((nsnull == aTextRangeList) || (nsnull == aReply)) - return NS_ERROR_NULL_POINTER; - - nsCOMPtr caretP; - nsresult result = SetInputMethodText(aCompositionString,aTextRangeList); - mIMEBufferLength = aCompositionString.Length(); - - if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED; - nsCOMPtr ps = do_QueryReferent(mPresShellWeak); - if (!ps) return NS_ERROR_NOT_INITIALIZED; - result = ps->GetCaret(getter_AddRefs(caretP)); - NS_ASSERTION(NS_SUCCEEDED(result), "cannot get caret"); - if(NS_SUCCEEDED(result)) { - result = caretP->GetWindowRelativeCoordinates(aReply->mCursorPosition,aReply->mCursorIsCollapsed); - NS_ASSERTION(NS_SUCCEEDED(result), "Cannot get window relative coordinates"); - } - return result; + return NS_ERROR_NOT_IMPLEMENTED; } #ifdef XP_MAC @@ -1620,16 +1558,41 @@ NS_IMETHODIMP nsEditor::InsertTextImpl(const nsString& aStringToInsert) if ((NS_FAILED(result)) || (nsnull==aggTxn)) { return NS_ERROR_OUT_OF_MEMORY; } - InsertTextTxn *txn; - result = CreateTxnForInsertText(aStringToInsert, nsnull, &txn); // insert at the current selection - if ((NS_SUCCEEDED(result)) && txn) { + + nsCOMPtr nodeAsText; + PRInt32 offset; + result = PrepareToInsertText(&nodeAsText, &offset); + + if (NS_SUCCEEDED(result)) + { + EditTxn *txn; + if (mInIMEMode) + { + if (!mIMETextNode) + { + mIMETextNode = nodeAsText; + mIMETextOffset = offset; + } +// else if (mIMETextNode != nodeAsText) || (mIMETextOffset+mIMEBufferLength != offset)) +// { +// // IME and we do not agree about where we are. Force a commit of +// // earlier ime txn. We don't have a way to do that yet. +// } + 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; BeginUpdateViewBatch(); -// aggTxn->AppendChild(txn); result = Do(aggTxn); result = Do(txn); EndUpdateViewBatch(); } - else if (NS_ERROR_EDITOR_NO_SELECTION==result) { + else if (NS_ERROR_EDITOR_NO_SELECTION==result) + { result = DoInitialInsert(aStringToInsert); } else if (NS_ERROR_EDITOR_NO_TEXTNODE==result) @@ -1685,6 +1648,59 @@ NS_IMETHODIMP nsEditor::InsertTextImpl(const nsString& aStringToInsert) return result; } +NS_IMETHODIMP nsEditor::PrepareToInsertText(nsCOMPtr *aOutTextNode, PRInt32 *aOutOffset) +{ + if (!aOutTextNode || !aOutOffset) return NS_ERROR_NULL_POINTER; + nsresult result = NS_OK; + nsCOMPtr nodeAsText; + + nsCOMPtr selection; + if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED; + nsCOMPtr ps = do_QueryReferent(mPresShellWeak); + if (!ps) return NS_ERROR_NOT_INITIALIZED; + result = ps->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection)); + if ((NS_SUCCEEDED(result)) && selection) + { + result = NS_ERROR_UNEXPECTED; + nsCOMPtr enumerator; + result = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_SUCCEEDED(result) && enumerator) + { + enumerator->First(); + nsCOMPtr currentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if ((NS_SUCCEEDED(result)) && (currentItem)) + { + result = NS_ERROR_UNEXPECTED; + nsCOMPtr range( do_QueryInterface(currentItem) ); + if (range) + { + nsCOMPtr node; + result = range->GetStartParent(getter_AddRefs(node)); + if ((NS_SUCCEEDED(result)) && (node)) + { + nodeAsText = do_QueryInterface(node); + range->GetStartOffset(aOutOffset); + if (nodeAsText) + { + *aOutTextNode = nodeAsText; + } + else + { + result = NS_ERROR_EDITOR_NO_TEXTNODE; + } + } + } + } + else + { + result = NS_ERROR_EDITOR_NO_SELECTION; + } + } + } + return result; +} + NS_IMETHODIMP nsEditor::SelectEntireDocument(nsIDOMSelection *aSelection) { nsresult result; @@ -1876,86 +1892,16 @@ nsEditor::NotifyDocumentListeners(TDocumentListenerNotification aNotificationTyp NS_IMETHODIMP nsEditor::CreateTxnForInsertText(const nsString & aStringToInsert, nsIDOMCharacterData *aTextNode, + PRInt32 aOffset, InsertTextTxn ** aTxn) { + if (!aTextNode || !aTxn) return NS_ERROR_NULL_POINTER; nsresult result; - PRInt32 offset; - nsCOMPtr nodeAsText; - if (aTextNode) { - nodeAsText = do_QueryInterface(aTextNode); - offset = 0; - result = NS_OK; - } - else - { - nsCOMPtr selection; - if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED; - nsCOMPtr ps = do_QueryReferent(mPresShellWeak); - if (!ps) return NS_ERROR_NOT_INITIALIZED; - result = ps->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) - { -#if 0 - // Trap the simple case where the collapsed selection - // is pointing to the beginning of a text node. - // That's where we should insert new text - // *** If we don't do this, we will return NS_ERROR_EDITOR_NO_TEXTNODE - // from the iterator block below. - // This may be OK, now that I fixed InsertText so it inserts - // at the offset of the selection anchor (i.e., the caret offset) - // instead of at offset+1 - PRBool collapsed; - result = selection->GetIsCollapsed(&collapsed); - if (NS_SUCCEEDED(result) && collapsed) - { - // Check if the node at selection offset is a textNode - // and use that with offset = 0. - } -#endif - result = NS_ERROR_UNEXPECTED; - nsCOMPtr enumerator; - result = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) - { - enumerator->First(); - nsCOMPtr currentItem; - result = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(result)) && (currentItem)) - { - result = NS_ERROR_UNEXPECTED; - nsCOMPtr range( do_QueryInterface(currentItem) ); - if (range) - { - nsCOMPtr node; - result = range->GetStartParent(getter_AddRefs(node)); - if ((NS_SUCCEEDED(result)) && (node)) - { - nodeAsText = do_QueryInterface(node); - range->GetStartOffset(&offset); - if (!nodeAsText) { - result = NS_ERROR_EDITOR_NO_TEXTNODE; - } - } - } - } - else - { - result = NS_ERROR_EDITOR_NO_SELECTION; - } - } - } - } - if (NS_SUCCEEDED(result) && nodeAsText) - { - result = TransactionFactory::GetNewTransaction(InsertTextTxn::GetCID(), (EditTxn **)aTxn); - if (nsnull!=*aTxn) { - result = (*aTxn)->Init(nodeAsText, offset, aStringToInsert, mPresShellWeak); - } - else { - result = NS_ERROR_OUT_OF_MEMORY; - } - } + 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); return result; } @@ -2014,8 +1960,24 @@ NS_IMETHODIMP nsEditor::DoInitialInsert(const nsString & aStringToInsert) newTextNode = do_QueryInterface(newNode); if (newTextNode) { - InsertTextTxn *insertTxn; - result = CreateTxnForInsertText(aStringToInsert, newTextNode, &insertTxn); + EditTxn *insertTxn; + if (mInIMEMode) + { + nsCOMPtr selection; + result = GetSelection(getter_AddRefs(selection)); + if ((NS_SUCCEEDED(result)) && selection) + { + selection->Collapse(newTextNode, 0); + mIMETextNode = newTextNode; + mIMETextOffset = 0; + mIMEBufferLength = 0; + result = CreateTxnForIMEText(aStringToInsert,(IMETextTxn**)&txn); + } + } + else + { + result = CreateTxnForInsertText(aStringToInsert, newTextNode, 0, (InsertTextTxn**)&txn); + } if (NS_SUCCEEDED(result)) { result = Do(insertTxn); } @@ -3263,120 +3225,8 @@ nsEditor::GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode) //END nsEditor Private methods -NS_IMETHODIMP -nsEditor::SetInputMethodText(const nsString& aStringToInsert, nsIPrivateTextRangeList *aTextRangeList) -{ - IMETextTxn *txn; - - nsresult result = CreateTxnForIMEText(aStringToInsert,aTextRangeList,&txn); // insert at the current selection - if ((NS_SUCCEEDED(result)) && txn) { - BeginUpdateViewBatch(); - result = Do(txn); - EndUpdateViewBatch(); - } - else if (NS_ERROR_EDITOR_NO_SELECTION==result) { - result = DoInitialInputMethodInsert(aStringToInsert,aTextRangeList); - } - else if (NS_ERROR_EDITOR_NO_TEXTNODE==result) - { - nsAutoEditBatch batchIt (this); - nsCOMPtr selection; - result = GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) - { - nsCOMPtr selectedNode; - PRInt32 offset; - result = selection->GetAnchorNode(getter_AddRefs(selectedNode)); - if (NS_SUCCEEDED(result) && NS_SUCCEEDED(selection->GetAnchorOffset(&offset)) && selectedNode) - { - nsCOMPtr newNode; - nsAutoString textNodeTag; - result = GetTextNodeTag(textNodeTag); - if (NS_FAILED(result)) { return result; } - result = CreateNode(textNodeTag, selectedNode, offset+1,getter_AddRefs(newNode)); - if (NS_SUCCEEDED(result) && newNode) - { - nsCOMPtrnewTextNode; - newTextNode = do_QueryInterface(newNode); - if (newTextNode) - { - nsAutoString placeholderText(" "); - newTextNode->SetData(placeholderText); - selection->Collapse(newNode, 0); - selection->Extend(newNode, 1); - result = SetInputMethodText(aStringToInsert,aTextRangeList); - } - } - } - } - } - - return result; -} - -NS_IMETHODIMP nsEditor::DoInitialInputMethodInsert(const nsString & aStringToInsert, nsIPrivateTextRangeList* aTextRangeList) -{ - if (!mDocWeak) { - return NS_ERROR_NOT_INITIALIZED; - } - - nsCOMPtrnodeList; - nsAutoString bodyTag = "body"; - nsCOMPtr doc = do_QueryReferent(mDocWeak); - if (!doc) return NS_ERROR_NOT_INITIALIZED; - nsresult result = doc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList)); - if ((NS_SUCCEEDED(result)) && nodeList) - { - PRUint32 count; - nodeList->GetLength(&count); - NS_ASSERTION(1==count, "there is not exactly 1 body in the document!"); - nsCOMPtrnode; - result = nodeList->Item(0, getter_AddRefs(node)); - if ((NS_SUCCEEDED(result)) && node) - { // now we've got the body tag. - // create transaction to insert the text node, - // and create a transaction to insert the text - CreateElementTxn *txn; - nsAutoString textNodeTag; - result = GetTextNodeTag(textNodeTag); - if (NS_FAILED(result)) { return result; } - result = CreateTxnForCreateElement(textNodeTag, node, 0, &txn); - if ((NS_SUCCEEDED(result)) && txn) - { - result = Do(txn); - if (NS_SUCCEEDED(result)) - { - nsCOMPtrnewNode; - txn->GetNewNode(getter_AddRefs(newNode)); - if ((NS_SUCCEEDED(result)) && newNode) - { - nsCOMPtrnewTextNode; - newTextNode = do_QueryInterface(newNode); - if (newTextNode) - { - mIMETextNode = newTextNode; - mIMETextOffset = 0; - mIMEBufferLength = 0; - - IMETextTxn *IMETxn; - result = CreateTxnForIMEText(aStringToInsert,aTextRangeList,&IMETxn); - if (NS_SUCCEEDED(result)) { - result = Do(IMETxn); - } - } - else { - result = NS_ERROR_UNEXPECTED; - } - } - } - } - } - } - - return result; -} /////////////////////////////////////////////////////////////////////////// // GetTag: digs out the atom for the tag of this node // @@ -4298,30 +4148,16 @@ NS_IMETHODIMP nsEditor::CreateAggregateTxnForDeleteSelection(nsIAtom *aTxnName, NS_IMETHODIMP nsEditor::CreateTxnForIMEText(const nsString & aStringToInsert, - nsIPrivateTextRangeList* aTextRangeList, IMETextTxn ** aTxn) { - NS_ASSERTION(aTextRangeList, "illegal value- null ptr- aTextRangeList"); NS_ASSERTION(aTxn, "illegal value- null ptr- aTxn"); - if((nsnull == aTextRangeList) || (nsnull == aTxn)) - return NS_ERROR_NULL_POINTER; - + if(!aTxn) return NS_ERROR_NULL_POINTER; + nsresult result; - if (mIMETextNode==nsnull) - result = BeginComposition(nsnull); - NS_ASSERTION( NS_SUCCEEDED(result), "BeginComposition failed"); - if(NS_FAILED(result)) - return result; - result = TransactionFactory::GetNewTransaction(IMETextTxn::GetCID(), (EditTxn **)aTxn); - NS_ASSERTION( NS_SUCCEEDED(result), "TransactionFactory::GetNewTransaction failed"); - if(NS_FAILED(result)) - return result; - if (nsnull!=*aTxn) { - result = (*aTxn)->Init(mIMETextNode,mIMETextOffset,mIMEBufferLength,aTextRangeList,aStringToInsert,mPresShellWeak); - NS_ASSERTION( NS_SUCCEEDED(result), "nsIMETextTxn::Init failed"); + result = (*aTxn)->Init(mIMETextNode,mIMETextOffset,mIMEBufferLength,mIMETextRangeList,aStringToInsert,mPresShellWeak); } else { result = NS_ERROR_OUT_OF_MEMORY; diff --git a/mozilla/editor/base/nsEditor.h b/mozilla/editor/base/nsEditor.h index e6301b2629c..4838e2eef5b 100644 --- a/mozilla/editor/base/nsEditor.h +++ b/mozilla/editor/base/nsEditor.h @@ -284,10 +284,10 @@ protected: */ NS_IMETHOD CreateTxnForInsertText(const nsString & aStringToInsert, nsIDOMCharacterData *aTextNode, + PRInt32 aOffset, InsertTextTxn ** aTxn); NS_IMETHOD CreateTxnForIMEText(const nsString & aStringToInsert, - nsIPrivateTextRangeList* aTextRangeList, IMETextTxn ** aTxn); /** create a transaction for adding a style sheet @@ -302,8 +302,7 @@ protected: */ NS_IMETHOD DoInitialInsert(const nsString & aStringToInsert); - NS_IMETHOD DoInitialInputMethodInsert(const nsString & aStringToInsert, nsIPrivateTextRangeList* aTextRangeList); - + NS_IMETHOD PrepareToInsertText(nsCOMPtr *aOutTextNode, PRInt32 *aOutOffset); NS_IMETHOD DeleteText(nsIDOMCharacterData *aElement, PRUint32 aOffset, @@ -323,8 +322,6 @@ protected: JoinElementTxn **aTxn); - NS_IMETHOD SetInputMethodText(const nsString& aStringToInsert, nsIPrivateTextRangeList *aTextRangeList); - // called each time we modify the document. Increments the mod // count of the doc. NS_IMETHOD IncDocModCount(PRInt32 inNumMods); @@ -622,9 +619,11 @@ protected: // // data necessary to build IME transactions // - nsCOMPtr mIMETextNode; - PRUint32 mIMETextOffset; - PRUint32 mIMEBufferLength; + 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 nsVoidArray* mActionListeners; nsCOMPtr mDocStateListeners; diff --git a/mozilla/editor/base/nsHTMLEditor.cpp b/mozilla/editor/base/nsHTMLEditor.cpp index 2c0b70ce33b..4ac9dd5d2be 100644 --- a/mozilla/editor/base/nsHTMLEditor.cpp +++ b/mozilla/editor/base/nsHTMLEditor.cpp @@ -113,6 +113,7 @@ static char hrefText[] = "href"; static char anchorTxt[] = "anchor"; static char namedanchorText[] = "namedanchor"; nsIAtom *nsHTMLEditor::gTypingTxnName; +nsIAtom *nsHTMLEditor::gIMETxnName; nsIAtom *nsHTMLEditor::gDeleteTxnName; @@ -214,6 +215,10 @@ nsHTMLEditor::nsHTMLEditor() gTypingTxnName = NS_NewAtom("Typing"); else NS_ADDREF(gTypingTxnName); + if (!gIMETxnName) + gIMETxnName = NS_NewAtom("IME"); + else + NS_ADDREF(gIMETxnName); if (!gDeleteTxnName) gDeleteTxnName = NS_NewAtom("Deleting"); else @@ -231,6 +236,14 @@ nsHTMLEditor::~nsHTMLEditor() } } + if (gIMETxnName) // we addref'd in the constructor + { // want to release it without nulling out the pointer. + refCount = gIMETxnName->Release(); + if (0==refCount) { + gIMETxnName = nsnull; + } + } + if (gDeleteTxnName) // we addref'd in the constructor { // want to release it without nulling out the pointer. refCount = gDeleteTxnName->Release(); @@ -3784,13 +3797,11 @@ nsHTMLEditor::SetCompositionString(const nsString& aCompositionString, nsIPrivat nsCOMPtr selection; nsresult result = GetSelection(getter_AddRefs(selection)); if (NS_FAILED(result)) return result; - nsTextRulesInfo ruleInfo(nsTextEditRules::kInsertTextIME); - PRBool cancel, handled; - result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); - if (cancel || NS_FAILED(result)) return result; + + nsAutoPlaceHolderBatch batch(this, gIMETxnName); + + result = InsertText(aCompositionString); - result = SetInputMethodText(aCompositionString,aTextRangeList); - if (NS_FAILED(result)) return result; mIMEBufferLength = aCompositionString.Length(); if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED; @@ -3799,7 +3810,6 @@ nsHTMLEditor::SetCompositionString(const nsString& aCompositionString, nsIPrivat ps->GetCaret(getter_AddRefs(caretP)); caretP->GetWindowRelativeCoordinates(aReply->mCursorPosition,aReply->mCursorIsCollapsed); - result = mRules->DidDoAction(selection, &ruleInfo, result); return result; } diff --git a/mozilla/editor/base/nsHTMLEditor.h b/mozilla/editor/base/nsHTMLEditor.h index 026c1a8961d..78f92ed74b2 100644 --- a/mozilla/editor/base/nsHTMLEditor.h +++ b/mozilla/editor/base/nsHTMLEditor.h @@ -483,6 +483,7 @@ protected: public: static nsIAtom *gTypingTxnName; + static nsIAtom *gIMETxnName; static nsIAtom *gDeleteTxnName; // friends diff --git a/mozilla/editor/base/nsIAbsorbingTransaction.h b/mozilla/editor/base/nsIAbsorbingTransaction.h index f5f9b41ee4b..a67ab8b05c5 100644 --- a/mozilla/editor/base/nsIAbsorbingTransaction.h +++ b/mozilla/editor/base/nsIAbsorbingTransaction.h @@ -53,6 +53,8 @@ public: NS_IMETHOD GetStartNodeAndOffset(nsCOMPtr *aTxnStartNode, PRInt32 *aTxnStartOffset)=0; NS_IMETHOD ForwardEndBatchTo(nsIAbsorbingTransaction *aForwardingAddress)=0; + + NS_IMETHOD Commit()=0; }; #endif // nsIAbsorbingTransaction_h__ diff --git a/mozilla/editor/libeditor/base/IMETextTxn.cpp b/mozilla/editor/libeditor/base/IMETextTxn.cpp index 3d9982c0275..26c3fdf8671 100644 --- a/mozilla/editor/libeditor/base/IMETextTxn.cpp +++ b/mozilla/editor/libeditor/base/IMETextTxn.cpp @@ -17,7 +17,6 @@ */ #include "IMETextTxn.h" -#include "IMECommitTxn.h" #include "nsEditor.h" #include "nsIDOMCharacterData.h" #include "nsIPrivateTextRange.h" @@ -176,23 +175,6 @@ NS_IMETHODIMP IMETextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction) return NS_OK; } - // - // second possible case is that we have a commit transaction - // - IMECommitTxn* commitTxn = nsnull; - result = aTransaction->QueryInterface(IMECommitTxn::GetCID(),(void**)&commitTxn); - if (commitTxn && NS_SUCCEEDED(NS_OK)) - { - (void)CollapseTextSelectionOnCommit(); - mFixed = PR_TRUE; - *aDidMerge = PR_TRUE; // absorbe the commit transaction -#ifdef DEBUG_TAGUE - printf("IMETextTxn assimilated IMECommitTxn%p\n", aTransaction); -#endif - NS_RELEASE(commitTxn); - return NS_OK; - } - *aDidMerge = PR_FALSE; return NS_OK; } @@ -292,26 +274,29 @@ NS_IMETHODIMP IMETextTxn::CollapseTextSelection(void) #endif // - // run through the text range list + // run through the text range list, if any // - result = mRangeList->GetLength(&textRangeListLength); - if (NS_SUCCEEDED(result)) + if (mRangeList) { - for(i=0;iItem(i,&textRange); - if (NS_SUCCEEDED(result)) - { - result = textRange->GetRangeType(&textRangeType); - if (textRangeType==nsIPrivateTextRange::TEXTRANGE_SELECTEDCONVERTEDTEXT) + result = mRangeList->GetLength(&textRangeListLength); + if (NS_SUCCEEDED(result)) + { + for(i=0;iItem(i,&textRange); + if (NS_SUCCEEDED(result)) { - haveSelectedRange = PR_TRUE; - textRange->GetRangeStart(&selectionStart); - textRange->GetRangeEnd(&selectionEnd); - } - if (textRangeType==nsIPrivateTextRange::TEXTRANGE_CARETPOSITION) - { - haveCaretPosition = PR_TRUE; - textRange->GetRangeStart(&caretPosition); + result = textRange->GetRangeType(&textRangeType); + if (textRangeType==nsIPrivateTextRange::TEXTRANGE_SELECTEDCONVERTEDTEXT) + { + haveSelectedRange = PR_TRUE; + textRange->GetRangeStart(&selectionStart); + textRange->GetRangeEnd(&selectionEnd); + } + if (textRangeType==nsIPrivateTextRange::TEXTRANGE_CARETPOSITION) + { + haveCaretPosition = PR_TRUE; + textRange->GetRangeStart(&caretPosition); + } } } } @@ -336,15 +321,3 @@ NS_IMETHODIMP IMETextTxn::CollapseTextSelection(void) return result; } -NS_IMETHODIMP IMETextTxn::CollapseTextSelectionOnCommit(void) -{ - nsCOMPtr selection; - nsCOMPtr ps = do_QueryReferent(mPresShellWeak); - if (!ps) return NS_ERROR_NOT_INITIALIZED; - nsresult result = ps->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection)); - if (NS_SUCCEEDED(result) && selection){ - result = selection->Collapse(mElement,mOffset+mStringToInsert.Length()); - } - - return result; -} diff --git a/mozilla/editor/libeditor/base/IMETextTxn.h b/mozilla/editor/libeditor/base/IMETextTxn.h index 2d965ddbdf7..f9cfe79af1b 100644 --- a/mozilla/editor/libeditor/base/IMETextTxn.h +++ b/mozilla/editor/libeditor/base/IMETextTxn.h @@ -101,7 +101,6 @@ public: protected: NS_IMETHOD CollapseTextSelection(void); - NS_IMETHOD CollapseTextSelectionOnCommit(void); /** the text element to operate upon */ nsCOMPtr mElement; diff --git a/mozilla/editor/libeditor/base/PlaceholderTxn.cpp b/mozilla/editor/libeditor/base/PlaceholderTxn.cpp index aea752cfa5d..8625e0e4b64 100644 --- a/mozilla/editor/libeditor/base/PlaceholderTxn.cpp +++ b/mozilla/editor/libeditor/base/PlaceholderTxn.cpp @@ -20,6 +20,7 @@ #include "nsVoidArray.h" #include "nsHTMLEditor.h" #include "nsIPresShell.h" +#include "IMETextTxn.h" #if defined(NS_DEBUG) && defined(DEBUG_buster) static PRBool gNoisy = PR_TRUE; @@ -31,7 +32,9 @@ static const PRBool gNoisy = PR_FALSE; PlaceholderTxn::PlaceholderTxn() : EditAggregateTxn(), mPresShellWeak(nsnull), mAbsorb(PR_TRUE), - mForwarding(nsnull) + mForwarding(nsnull), + mIMETextTxn(nsnull), + mCommitted(PR_FALSE) { SetTransactionDescriptionID( kTransactionID ); /* log description initialized in parent constructor */ @@ -97,7 +100,7 @@ NS_IMETHODIMP PlaceholderTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransact *aDidMerge=PR_FALSE; nsresult res = NS_OK; - + if (mForwarding) { NS_NOTREACHED("tried to merge into a placeholder that was in forwarding mode!"); @@ -107,14 +110,45 @@ NS_IMETHODIMP PlaceholderTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransact EditTxn *editTxn = (EditTxn*)aTransaction; //XXX: hack, not safe! need nsIEditTransaction! if (PR_TRUE==mAbsorb) { // yep, it's one of ours. Assimilate it. - AppendChild(editTxn); + IMETextTxn* otherTxn = nsnull; + if (NS_SUCCEEDED(aTransaction->QueryInterface(IMETextTxn::GetCID(),(void**)&otherTxn)) && otherTxn) + { + // special handling for IMETextTxn's: they need to merge with any previous + // IMETextTxn in this placeholder, if possible. + if (!mIMETextTxn) + { + // this is the first IME txn in the placeholder + mIMETextTxn =otherTxn; + AppendChild(editTxn); + } + else + { + PRBool didMerge; + mIMETextTxn->Merge(&didMerge, otherTxn); + if (!didMerge) + { + // it wouldn't merge. Earlier IME txn is already commited and will + // not absorb frther IME txns. So just stack this one after it + // and remember it as a candidate for furthre merges. + mIMETextTxn =otherTxn; + AppendChild(editTxn); + } + } + NS_IF_RELEASE(otherTxn); + } + else + { + AppendChild(editTxn); + } *aDidMerge = PR_TRUE; if (gNoisy) { printf("Placeholder txn assimilated %p\n", aTransaction); } } else - { // merge typing or deletion transactions if the selection matches - if ( (mName.get() == nsHTMLEditor::gTypingTxnName) || - (mName.get() == nsHTMLEditor::gDeleteTxnName) ) + { // merge typing or IME or deletion transactions if the selection matches + if (((mName.get() == nsHTMLEditor::gTypingTxnName) || + (mName.get() == nsHTMLEditor::gIMETxnName) || + (mName.get() == nsHTMLEditor::gDeleteTxnName)) + && !mCommitted ) { nsCOMPtr plcTxn;// = do_QueryInterface(editTxn); // cant do_QueryInterface() above due to our broken transaction interfaces. @@ -139,6 +173,7 @@ NS_IMETHODIMP PlaceholderTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransact *aDidMerge = PR_TRUE; } } + NS_IF_RELEASE(atom); } } } @@ -168,8 +203,9 @@ NS_IMETHODIMP PlaceholderTxn::EndPlaceHolderBatch() if (plcTxn) plcTxn->EndPlaceHolderBatch(); } - // if we are a typing or deleting transaction, remember our selection state + // if we are a typing or IME or deleting transaction, remember our selection state if ( (mName.get() == nsHTMLEditor::gTypingTxnName) || + (mName.get() == nsHTMLEditor::gIMETxnName) || (mName.get() == nsHTMLEditor::gDeleteTxnName) ) { nsCOMPtr ps = do_QueryReferent(mPresShellWeak); @@ -190,7 +226,11 @@ NS_IMETHODIMP PlaceholderTxn::ForwardEndBatchTo(nsIAbsorbingTransaction *aForwar return NS_OK; } - +NS_IMETHODIMP PlaceholderTxn::Commit() +{ + mCommitted = PR_TRUE; + return NS_OK; +} diff --git a/mozilla/editor/libeditor/base/PlaceholderTxn.h b/mozilla/editor/libeditor/base/PlaceholderTxn.h index 5ad13ec7d02..56cc01677f2 100644 --- a/mozilla/editor/libeditor/base/PlaceholderTxn.h +++ b/mozilla/editor/libeditor/base/PlaceholderTxn.h @@ -32,6 +32,7 @@ {0x86, 0xde, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74} } class nsHTMLEditor; +class IMETextTxn; /** * An aggregate transaction that knows how to absorb all subsequent @@ -77,6 +78,8 @@ public: NS_IMETHOD ForwardEndBatchTo(nsIAbsorbingTransaction *aForwardingAddress); + NS_IMETHOD Commit(); + friend class TransactionFactory; enum { kTransactionID = 11260 }; @@ -84,11 +87,14 @@ public: protected: /** the presentation shell, which we'll need to get the selection */ - nsWeakPtr mPresShellWeak; // weak reference to the nsIPresShell - PRBool mAbsorb; + nsWeakPtr mPresShellWeak; // weak reference to the nsIPresShell + PRBool mAbsorb; // do we auto absorb any and all transaction? nsCOMPtr mStartNode, mEndNode; // selection nodes at beginning and end of operation - PRInt32 mStartOffset, mEndOffset; // selection offsets at beginning and end of operation - nsWeakPtr mForwarding; + PRInt32 mStartOffset, mEndOffset; // selection offsets at beginning and end of operation + nsWeakPtr mForwarding; + IMETextTxn *mIMETextTxn; // first IME txn in this placeholder - used for IME merging + // non-owning for now - cant nsCOMPtr it due to broken transaction interfaces + PRBool mCommitted; // do we stop auto absorbing any matching placeholder txns? }; diff --git a/mozilla/editor/libeditor/base/TransactionFactory.cpp b/mozilla/editor/libeditor/base/TransactionFactory.cpp index c9ff0cf8336..d4b04734517 100644 --- a/mozilla/editor/libeditor/base/TransactionFactory.cpp +++ b/mozilla/editor/libeditor/base/TransactionFactory.cpp @@ -31,7 +31,6 @@ #include "JoinElementTxn.h" #include "nsStyleSheetTxns.h" #include "IMETextTxn.h" -#include "IMECommitTxn.h" TransactionFactory::TransactionFactory() { @@ -68,8 +67,6 @@ TransactionFactory::GetNewTransaction(REFNSIID aTxnType, EditTxn **aResult) *aResult = new EditAggregateTxn(); else if (aTxnType.Equals(IMETextTxn::GetCID())) *aResult = new IMETextTxn(); - else if (aTxnType.Equals(IMECommitTxn::GetCID())) - *aResult = new IMECommitTxn(); else if (aTxnType.Equals(AddStyleSheetTxn::GetCID())) *aResult = new AddStyleSheetTxn(); else if (aTxnType.Equals(RemoveStyleSheetTxn::GetCID())) diff --git a/mozilla/editor/libeditor/base/nsEditor.cpp b/mozilla/editor/libeditor/base/nsEditor.cpp index bf7ca0ab95e..cd4560373ee 100644 --- a/mozilla/editor/libeditor/base/nsEditor.cpp +++ b/mozilla/editor/libeditor/base/nsEditor.cpp @@ -84,7 +84,6 @@ #include "JoinElementTxn.h" #include "nsStyleSheetTxns.h" #include "IMETextTxn.h" -#include "IMECommitTxn.h" // #define HACK_FORCE_REDRAW 1 @@ -151,6 +150,11 @@ nsEditor::nsEditor() , mPlaceHolderBatch(0) , mTxnStartNode(nsnull) , mTxnStartOffset(0) +, mInIMEMode(PR_FALSE) +, mIMETextRangeList(nsnull) +, mIMETextNode(nsnull) +, mIMETextOffset(0) +, mIMEBufferLength(0) , mActionListeners(nsnull) , mDocDirtyState(-1) , mDocWeak(nsnull) @@ -184,8 +188,7 @@ nsEditor::~nsEditor() /* shut down all classes that needed initialization */ InsertTextTxn::ClassShutdown(); IMETextTxn::ClassShutdown(); - IMECommitTxn::ClassShutdown(); - + PR_AtomicDecrement(&gInstanceCount); } @@ -269,7 +272,6 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell, PRUint32 aFlags) /* initalize IME stuff */ IMETextTxn::ClassInit(); - IMECommitTxn::ClassInit(); mIMETextNode = do_QueryInterface(nsnull); mIMETextOffset = 0; mIMEBufferLength = 0; @@ -712,7 +714,7 @@ NS_IMETHODIMP nsEditor::EndOfDocument() result = nodeList->Item(0, getter_AddRefs(bodyNode)); if ((NS_SUCCEEDED(result)) && bodyNode) { - nsCOMPtr lastChild; // = GetDeepLastChild(bodyNode); + nsCOMPtr lastChild; // = GetDeepLastChild(bodyNode); result = GetLastEditableNode(bodyNode, getter_AddRefs(lastChild)); if ((NS_SUCCEEDED(result)) && lastChild) { @@ -1321,8 +1323,6 @@ nsEditor::DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed) // // The BeingComposition method is called from the Editor Composition event listeners. -// It caches the current text node and offset which is subsequently used for the -// created of IMETextTxn's. // NS_IMETHODIMP nsEditor::BeginComposition(nsTextEventReply* aReply) @@ -1331,7 +1331,6 @@ nsEditor::BeginComposition(nsTextEventReply* aReply) printf("nsEditor::StartComposition\n"); #endif nsresult result; - PRInt32 offset; nsCOMPtr selection; nsCOMPtr nodeAsText; nsCOMPtr caretP; @@ -1344,52 +1343,8 @@ nsEditor::BeginComposition(nsTextEventReply* aReply) caretP->GetWindowRelativeCoordinates(aReply->mCursorPosition,aReply->mCursorIsCollapsed); } } - result = ps->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) - { - result = NS_ERROR_UNEXPECTED; - nsCOMPtr enumerator; - result = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) - { - enumerator->First(); - nsCOMPtr currentItem; - result = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(result)) && (currentItem)) - { - result = NS_ERROR_UNEXPECTED; - nsCOMPtr range(do_QueryInterface(currentItem)); - if (range) - { - nsCOMPtr node; - result = range->GetStartParent(getter_AddRefs(node)); - if ((NS_SUCCEEDED(result)) && (node)) - { - nodeAsText = do_QueryInterface(node); - NS_ASSERTION(nodeAsText, "cannot get Text Node"); - range->GetStartOffset(&offset); - if (!nodeAsText) { - result = NS_ERROR_EDITOR_NO_TEXTNODE; - } - } - } - } - else - { - result = NS_ERROR_EDITOR_NO_SELECTION; - } - } - } - if (NS_SUCCEEDED(result) && nodeAsText) - { - // - // store the information needed to construct IME transactions for this composition - // - mIMETextNode = nodeAsText; - mIMETextOffset = offset; - mIMEBufferLength = 0; - } + mInIMEMode = PR_TRUE; return result; } @@ -1397,20 +1352,20 @@ nsEditor::BeginComposition(nsTextEventReply* aReply) NS_IMETHODIMP nsEditor::EndComposition(void) { - nsresult result; - IMECommitTxn *commitTxn; + if (!mInIMEMode) return NS_OK; // nothing to do - // - // create the commit transaction..we can do it directly from the transaction mgr - // - result = TransactionFactory::GetNewTransaction(IMECommitTxn::GetCID(), (EditTxn**)&commitTxn); - if (NS_SUCCEEDED(result) && commitTxn!=nsnull) + nsresult result; + + // commit the IME transaction..we can get at it via the transaction mgr. + // Note that this means IME won't work without an undo stack! + if (mTxnMgr) { - result = commitTxn->Init(); - NS_ASSERTION(NS_SUCCEEDED(result), "commitTxt->Init failed"); - if(NS_SUCCEEDED(result)) { - result = Do(commitTxn); - NS_ASSERTION(NS_SUCCEEDED(result), "nsEditor::Do failed"); + nsCOMPtr txn; + result = mTxnMgr->PeekUndoStack(getter_AddRefs(txn)); + nsCOMPtr plcTxn = do_QueryInterface(txn); + if (plcTxn) + { + result = plcTxn->Commit(); } } @@ -1418,6 +1373,7 @@ nsEditor::EndComposition(void) mIMETextNode = do_QueryInterface(nsnull); mIMETextOffset = 0; mIMEBufferLength = 0; + mInIMEMode = PR_FALSE; return result; } @@ -1425,25 +1381,7 @@ nsEditor::EndComposition(void) NS_IMETHODIMP nsEditor::SetCompositionString(const nsString& aCompositionString, nsIPrivateTextRangeList* aTextRangeList,nsTextEventReply* aReply) { - NS_ASSERTION(aTextRangeList, "null ptr- aTextRangeList"); - NS_ASSERTION(aReply, "null ptr- aReply"); - if((nsnull == aTextRangeList) || (nsnull == aReply)) - return NS_ERROR_NULL_POINTER; - - nsCOMPtr caretP; - nsresult result = SetInputMethodText(aCompositionString,aTextRangeList); - mIMEBufferLength = aCompositionString.Length(); - - if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED; - nsCOMPtr ps = do_QueryReferent(mPresShellWeak); - if (!ps) return NS_ERROR_NOT_INITIALIZED; - result = ps->GetCaret(getter_AddRefs(caretP)); - NS_ASSERTION(NS_SUCCEEDED(result), "cannot get caret"); - if(NS_SUCCEEDED(result)) { - result = caretP->GetWindowRelativeCoordinates(aReply->mCursorPosition,aReply->mCursorIsCollapsed); - NS_ASSERTION(NS_SUCCEEDED(result), "Cannot get window relative coordinates"); - } - return result; + return NS_ERROR_NOT_IMPLEMENTED; } #ifdef XP_MAC @@ -1620,16 +1558,41 @@ NS_IMETHODIMP nsEditor::InsertTextImpl(const nsString& aStringToInsert) if ((NS_FAILED(result)) || (nsnull==aggTxn)) { return NS_ERROR_OUT_OF_MEMORY; } - InsertTextTxn *txn; - result = CreateTxnForInsertText(aStringToInsert, nsnull, &txn); // insert at the current selection - if ((NS_SUCCEEDED(result)) && txn) { + + nsCOMPtr nodeAsText; + PRInt32 offset; + result = PrepareToInsertText(&nodeAsText, &offset); + + if (NS_SUCCEEDED(result)) + { + EditTxn *txn; + if (mInIMEMode) + { + if (!mIMETextNode) + { + mIMETextNode = nodeAsText; + mIMETextOffset = offset; + } +// else if (mIMETextNode != nodeAsText) || (mIMETextOffset+mIMEBufferLength != offset)) +// { +// // IME and we do not agree about where we are. Force a commit of +// // earlier ime txn. We don't have a way to do that yet. +// } + 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; BeginUpdateViewBatch(); -// aggTxn->AppendChild(txn); result = Do(aggTxn); result = Do(txn); EndUpdateViewBatch(); } - else if (NS_ERROR_EDITOR_NO_SELECTION==result) { + else if (NS_ERROR_EDITOR_NO_SELECTION==result) + { result = DoInitialInsert(aStringToInsert); } else if (NS_ERROR_EDITOR_NO_TEXTNODE==result) @@ -1685,6 +1648,59 @@ NS_IMETHODIMP nsEditor::InsertTextImpl(const nsString& aStringToInsert) return result; } +NS_IMETHODIMP nsEditor::PrepareToInsertText(nsCOMPtr *aOutTextNode, PRInt32 *aOutOffset) +{ + if (!aOutTextNode || !aOutOffset) return NS_ERROR_NULL_POINTER; + nsresult result = NS_OK; + nsCOMPtr nodeAsText; + + nsCOMPtr selection; + if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED; + nsCOMPtr ps = do_QueryReferent(mPresShellWeak); + if (!ps) return NS_ERROR_NOT_INITIALIZED; + result = ps->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection)); + if ((NS_SUCCEEDED(result)) && selection) + { + result = NS_ERROR_UNEXPECTED; + nsCOMPtr enumerator; + result = selection->GetEnumerator(getter_AddRefs(enumerator)); + if (NS_SUCCEEDED(result) && enumerator) + { + enumerator->First(); + nsCOMPtr currentItem; + result = enumerator->CurrentItem(getter_AddRefs(currentItem)); + if ((NS_SUCCEEDED(result)) && (currentItem)) + { + result = NS_ERROR_UNEXPECTED; + nsCOMPtr range( do_QueryInterface(currentItem) ); + if (range) + { + nsCOMPtr node; + result = range->GetStartParent(getter_AddRefs(node)); + if ((NS_SUCCEEDED(result)) && (node)) + { + nodeAsText = do_QueryInterface(node); + range->GetStartOffset(aOutOffset); + if (nodeAsText) + { + *aOutTextNode = nodeAsText; + } + else + { + result = NS_ERROR_EDITOR_NO_TEXTNODE; + } + } + } + } + else + { + result = NS_ERROR_EDITOR_NO_SELECTION; + } + } + } + return result; +} + NS_IMETHODIMP nsEditor::SelectEntireDocument(nsIDOMSelection *aSelection) { nsresult result; @@ -1876,86 +1892,16 @@ nsEditor::NotifyDocumentListeners(TDocumentListenerNotification aNotificationTyp NS_IMETHODIMP nsEditor::CreateTxnForInsertText(const nsString & aStringToInsert, nsIDOMCharacterData *aTextNode, + PRInt32 aOffset, InsertTextTxn ** aTxn) { + if (!aTextNode || !aTxn) return NS_ERROR_NULL_POINTER; nsresult result; - PRInt32 offset; - nsCOMPtr nodeAsText; - if (aTextNode) { - nodeAsText = do_QueryInterface(aTextNode); - offset = 0; - result = NS_OK; - } - else - { - nsCOMPtr selection; - if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED; - nsCOMPtr ps = do_QueryReferent(mPresShellWeak); - if (!ps) return NS_ERROR_NOT_INITIALIZED; - result = ps->GetSelection(SELECTION_NORMAL, getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) - { -#if 0 - // Trap the simple case where the collapsed selection - // is pointing to the beginning of a text node. - // That's where we should insert new text - // *** If we don't do this, we will return NS_ERROR_EDITOR_NO_TEXTNODE - // from the iterator block below. - // This may be OK, now that I fixed InsertText so it inserts - // at the offset of the selection anchor (i.e., the caret offset) - // instead of at offset+1 - PRBool collapsed; - result = selection->GetIsCollapsed(&collapsed); - if (NS_SUCCEEDED(result) && collapsed) - { - // Check if the node at selection offset is a textNode - // and use that with offset = 0. - } -#endif - result = NS_ERROR_UNEXPECTED; - nsCOMPtr enumerator; - result = selection->GetEnumerator(getter_AddRefs(enumerator)); - if (NS_SUCCEEDED(result) && enumerator) - { - enumerator->First(); - nsCOMPtr currentItem; - result = enumerator->CurrentItem(getter_AddRefs(currentItem)); - if ((NS_SUCCEEDED(result)) && (currentItem)) - { - result = NS_ERROR_UNEXPECTED; - nsCOMPtr range( do_QueryInterface(currentItem) ); - if (range) - { - nsCOMPtr node; - result = range->GetStartParent(getter_AddRefs(node)); - if ((NS_SUCCEEDED(result)) && (node)) - { - nodeAsText = do_QueryInterface(node); - range->GetStartOffset(&offset); - if (!nodeAsText) { - result = NS_ERROR_EDITOR_NO_TEXTNODE; - } - } - } - } - else - { - result = NS_ERROR_EDITOR_NO_SELECTION; - } - } - } - } - if (NS_SUCCEEDED(result) && nodeAsText) - { - result = TransactionFactory::GetNewTransaction(InsertTextTxn::GetCID(), (EditTxn **)aTxn); - if (nsnull!=*aTxn) { - result = (*aTxn)->Init(nodeAsText, offset, aStringToInsert, mPresShellWeak); - } - else { - result = NS_ERROR_OUT_OF_MEMORY; - } - } + 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); return result; } @@ -2014,8 +1960,24 @@ NS_IMETHODIMP nsEditor::DoInitialInsert(const nsString & aStringToInsert) newTextNode = do_QueryInterface(newNode); if (newTextNode) { - InsertTextTxn *insertTxn; - result = CreateTxnForInsertText(aStringToInsert, newTextNode, &insertTxn); + EditTxn *insertTxn; + if (mInIMEMode) + { + nsCOMPtr selection; + result = GetSelection(getter_AddRefs(selection)); + if ((NS_SUCCEEDED(result)) && selection) + { + selection->Collapse(newTextNode, 0); + mIMETextNode = newTextNode; + mIMETextOffset = 0; + mIMEBufferLength = 0; + result = CreateTxnForIMEText(aStringToInsert,(IMETextTxn**)&txn); + } + } + else + { + result = CreateTxnForInsertText(aStringToInsert, newTextNode, 0, (InsertTextTxn**)&txn); + } if (NS_SUCCEEDED(result)) { result = Do(insertTxn); } @@ -3263,120 +3225,8 @@ nsEditor::GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode) //END nsEditor Private methods -NS_IMETHODIMP -nsEditor::SetInputMethodText(const nsString& aStringToInsert, nsIPrivateTextRangeList *aTextRangeList) -{ - IMETextTxn *txn; - - nsresult result = CreateTxnForIMEText(aStringToInsert,aTextRangeList,&txn); // insert at the current selection - if ((NS_SUCCEEDED(result)) && txn) { - BeginUpdateViewBatch(); - result = Do(txn); - EndUpdateViewBatch(); - } - else if (NS_ERROR_EDITOR_NO_SELECTION==result) { - result = DoInitialInputMethodInsert(aStringToInsert,aTextRangeList); - } - else if (NS_ERROR_EDITOR_NO_TEXTNODE==result) - { - nsAutoEditBatch batchIt (this); - nsCOMPtr selection; - result = GetSelection(getter_AddRefs(selection)); - if ((NS_SUCCEEDED(result)) && selection) - { - nsCOMPtr selectedNode; - PRInt32 offset; - result = selection->GetAnchorNode(getter_AddRefs(selectedNode)); - if (NS_SUCCEEDED(result) && NS_SUCCEEDED(selection->GetAnchorOffset(&offset)) && selectedNode) - { - nsCOMPtr newNode; - nsAutoString textNodeTag; - result = GetTextNodeTag(textNodeTag); - if (NS_FAILED(result)) { return result; } - result = CreateNode(textNodeTag, selectedNode, offset+1,getter_AddRefs(newNode)); - if (NS_SUCCEEDED(result) && newNode) - { - nsCOMPtrnewTextNode; - newTextNode = do_QueryInterface(newNode); - if (newTextNode) - { - nsAutoString placeholderText(" "); - newTextNode->SetData(placeholderText); - selection->Collapse(newNode, 0); - selection->Extend(newNode, 1); - result = SetInputMethodText(aStringToInsert,aTextRangeList); - } - } - } - } - } - - return result; -} - -NS_IMETHODIMP nsEditor::DoInitialInputMethodInsert(const nsString & aStringToInsert, nsIPrivateTextRangeList* aTextRangeList) -{ - if (!mDocWeak) { - return NS_ERROR_NOT_INITIALIZED; - } - - nsCOMPtrnodeList; - nsAutoString bodyTag = "body"; - nsCOMPtr doc = do_QueryReferent(mDocWeak); - if (!doc) return NS_ERROR_NOT_INITIALIZED; - nsresult result = doc->GetElementsByTagName(bodyTag, getter_AddRefs(nodeList)); - if ((NS_SUCCEEDED(result)) && nodeList) - { - PRUint32 count; - nodeList->GetLength(&count); - NS_ASSERTION(1==count, "there is not exactly 1 body in the document!"); - nsCOMPtrnode; - result = nodeList->Item(0, getter_AddRefs(node)); - if ((NS_SUCCEEDED(result)) && node) - { // now we've got the body tag. - // create transaction to insert the text node, - // and create a transaction to insert the text - CreateElementTxn *txn; - nsAutoString textNodeTag; - result = GetTextNodeTag(textNodeTag); - if (NS_FAILED(result)) { return result; } - result = CreateTxnForCreateElement(textNodeTag, node, 0, &txn); - if ((NS_SUCCEEDED(result)) && txn) - { - result = Do(txn); - if (NS_SUCCEEDED(result)) - { - nsCOMPtrnewNode; - txn->GetNewNode(getter_AddRefs(newNode)); - if ((NS_SUCCEEDED(result)) && newNode) - { - nsCOMPtrnewTextNode; - newTextNode = do_QueryInterface(newNode); - if (newTextNode) - { - mIMETextNode = newTextNode; - mIMETextOffset = 0; - mIMEBufferLength = 0; - - IMETextTxn *IMETxn; - result = CreateTxnForIMEText(aStringToInsert,aTextRangeList,&IMETxn); - if (NS_SUCCEEDED(result)) { - result = Do(IMETxn); - } - } - else { - result = NS_ERROR_UNEXPECTED; - } - } - } - } - } - } - - return result; -} /////////////////////////////////////////////////////////////////////////// // GetTag: digs out the atom for the tag of this node // @@ -4298,30 +4148,16 @@ NS_IMETHODIMP nsEditor::CreateAggregateTxnForDeleteSelection(nsIAtom *aTxnName, NS_IMETHODIMP nsEditor::CreateTxnForIMEText(const nsString & aStringToInsert, - nsIPrivateTextRangeList* aTextRangeList, IMETextTxn ** aTxn) { - NS_ASSERTION(aTextRangeList, "illegal value- null ptr- aTextRangeList"); NS_ASSERTION(aTxn, "illegal value- null ptr- aTxn"); - if((nsnull == aTextRangeList) || (nsnull == aTxn)) - return NS_ERROR_NULL_POINTER; - + if(!aTxn) return NS_ERROR_NULL_POINTER; + nsresult result; - if (mIMETextNode==nsnull) - result = BeginComposition(nsnull); - NS_ASSERTION( NS_SUCCEEDED(result), "BeginComposition failed"); - if(NS_FAILED(result)) - return result; - result = TransactionFactory::GetNewTransaction(IMETextTxn::GetCID(), (EditTxn **)aTxn); - NS_ASSERTION( NS_SUCCEEDED(result), "TransactionFactory::GetNewTransaction failed"); - if(NS_FAILED(result)) - return result; - if (nsnull!=*aTxn) { - result = (*aTxn)->Init(mIMETextNode,mIMETextOffset,mIMEBufferLength,aTextRangeList,aStringToInsert,mPresShellWeak); - NS_ASSERTION( NS_SUCCEEDED(result), "nsIMETextTxn::Init failed"); + result = (*aTxn)->Init(mIMETextNode,mIMETextOffset,mIMEBufferLength,mIMETextRangeList,aStringToInsert,mPresShellWeak); } else { result = NS_ERROR_OUT_OF_MEMORY; diff --git a/mozilla/editor/libeditor/base/nsEditor.h b/mozilla/editor/libeditor/base/nsEditor.h index e6301b2629c..4838e2eef5b 100644 --- a/mozilla/editor/libeditor/base/nsEditor.h +++ b/mozilla/editor/libeditor/base/nsEditor.h @@ -284,10 +284,10 @@ protected: */ NS_IMETHOD CreateTxnForInsertText(const nsString & aStringToInsert, nsIDOMCharacterData *aTextNode, + PRInt32 aOffset, InsertTextTxn ** aTxn); NS_IMETHOD CreateTxnForIMEText(const nsString & aStringToInsert, - nsIPrivateTextRangeList* aTextRangeList, IMETextTxn ** aTxn); /** create a transaction for adding a style sheet @@ -302,8 +302,7 @@ protected: */ NS_IMETHOD DoInitialInsert(const nsString & aStringToInsert); - NS_IMETHOD DoInitialInputMethodInsert(const nsString & aStringToInsert, nsIPrivateTextRangeList* aTextRangeList); - + NS_IMETHOD PrepareToInsertText(nsCOMPtr *aOutTextNode, PRInt32 *aOutOffset); NS_IMETHOD DeleteText(nsIDOMCharacterData *aElement, PRUint32 aOffset, @@ -323,8 +322,6 @@ protected: JoinElementTxn **aTxn); - NS_IMETHOD SetInputMethodText(const nsString& aStringToInsert, nsIPrivateTextRangeList *aTextRangeList); - // called each time we modify the document. Increments the mod // count of the doc. NS_IMETHOD IncDocModCount(PRInt32 inNumMods); @@ -622,9 +619,11 @@ protected: // // data necessary to build IME transactions // - nsCOMPtr mIMETextNode; - PRUint32 mIMETextOffset; - PRUint32 mIMEBufferLength; + 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 nsVoidArray* mActionListeners; nsCOMPtr mDocStateListeners; diff --git a/mozilla/editor/libeditor/base/nsIAbsorbingTransaction.h b/mozilla/editor/libeditor/base/nsIAbsorbingTransaction.h index f5f9b41ee4b..a67ab8b05c5 100644 --- a/mozilla/editor/libeditor/base/nsIAbsorbingTransaction.h +++ b/mozilla/editor/libeditor/base/nsIAbsorbingTransaction.h @@ -53,6 +53,8 @@ public: NS_IMETHOD GetStartNodeAndOffset(nsCOMPtr *aTxnStartNode, PRInt32 *aTxnStartOffset)=0; NS_IMETHOD ForwardEndBatchTo(nsIAbsorbingTransaction *aForwardingAddress)=0; + + NS_IMETHOD Commit()=0; }; #endif // nsIAbsorbingTransaction_h__ diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp index 2c0b70ce33b..4ac9dd5d2be 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp @@ -113,6 +113,7 @@ static char hrefText[] = "href"; static char anchorTxt[] = "anchor"; static char namedanchorText[] = "namedanchor"; nsIAtom *nsHTMLEditor::gTypingTxnName; +nsIAtom *nsHTMLEditor::gIMETxnName; nsIAtom *nsHTMLEditor::gDeleteTxnName; @@ -214,6 +215,10 @@ nsHTMLEditor::nsHTMLEditor() gTypingTxnName = NS_NewAtom("Typing"); else NS_ADDREF(gTypingTxnName); + if (!gIMETxnName) + gIMETxnName = NS_NewAtom("IME"); + else + NS_ADDREF(gIMETxnName); if (!gDeleteTxnName) gDeleteTxnName = NS_NewAtom("Deleting"); else @@ -231,6 +236,14 @@ nsHTMLEditor::~nsHTMLEditor() } } + if (gIMETxnName) // we addref'd in the constructor + { // want to release it without nulling out the pointer. + refCount = gIMETxnName->Release(); + if (0==refCount) { + gIMETxnName = nsnull; + } + } + if (gDeleteTxnName) // we addref'd in the constructor { // want to release it without nulling out the pointer. refCount = gDeleteTxnName->Release(); @@ -3784,13 +3797,11 @@ nsHTMLEditor::SetCompositionString(const nsString& aCompositionString, nsIPrivat nsCOMPtr selection; nsresult result = GetSelection(getter_AddRefs(selection)); if (NS_FAILED(result)) return result; - nsTextRulesInfo ruleInfo(nsTextEditRules::kInsertTextIME); - PRBool cancel, handled; - result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); - if (cancel || NS_FAILED(result)) return result; + + nsAutoPlaceHolderBatch batch(this, gIMETxnName); + + result = InsertText(aCompositionString); - result = SetInputMethodText(aCompositionString,aTextRangeList); - if (NS_FAILED(result)) return result; mIMEBufferLength = aCompositionString.Length(); if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED; @@ -3799,7 +3810,6 @@ nsHTMLEditor::SetCompositionString(const nsString& aCompositionString, nsIPrivat ps->GetCaret(getter_AddRefs(caretP)); caretP->GetWindowRelativeCoordinates(aReply->mCursorPosition,aReply->mCursorIsCollapsed); - result = mRules->DidDoAction(selection, &ruleInfo, result); return result; } diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.h b/mozilla/editor/libeditor/html/nsHTMLEditor.h index 026c1a8961d..78f92ed74b2 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.h +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.h @@ -483,6 +483,7 @@ protected: public: static nsIAtom *gTypingTxnName; + static nsIAtom *gIMETxnName; static nsIAtom *gDeleteTxnName; // friends