From dab8e009ec28b13621deb0169f3d09e0fb652322 Mon Sep 17 00:00:00 2001 From: "jfrancis%netscape.com" Date: Sun, 22 Dec 2002 01:51:14 +0000 Subject: [PATCH] editor fixes for: 180034 editor should respect the select_all style 183836 New list item should not reset inline styles 179384 Merging blocks via forward delete sends selection to front of document 98434 IME does not work correctly at the last characters in the text field (patch courtesy of Shotaro Kamio) r=jfrancis,brade,cmanske sr=kin git-svn-id: svn://10.0.0.236/trunk@135560 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/editor/libeditor/base/nsEditor.cpp | 45 ++++++++++ mozilla/editor/libeditor/base/nsEditor.h | 15 ++-- .../editor/libeditor/base/nsEditorUtils.cpp | 44 ++++++++++ mozilla/editor/libeditor/base/nsEditorUtils.h | 7 ++ .../editor/libeditor/base/nsIEditProperty.h | 1 + .../libeditor/base/nsSelectionState.cpp | 38 ++++++++- .../editor/libeditor/html/nsEditProperty.cpp | 3 + .../libeditor/html/nsHTMLDataTransfer.cpp | 4 +- .../editor/libeditor/html/nsHTMLEditRules.cpp | 85 +++++++++++-------- .../editor/libeditor/html/nsHTMLEditUtils.cpp | 41 --------- .../editor/libeditor/html/nsHTMLEditUtils.h | 2 - .../editor/libeditor/html/nsHTMLEditor.cpp | 66 ++++++++++++-- mozilla/editor/libeditor/html/nsHTMLEditor.h | 6 ++ .../libeditor/text/nsPlaintextEditor.cpp | 3 +- .../editor/libeditor/text/nsPlaintextEditor.h | 1 - .../editor/libeditor/text/nsTextEditRules.cpp | 10 ++- 16 files changed, 275 insertions(+), 96 deletions(-) diff --git a/mozilla/editor/libeditor/base/nsEditor.cpp b/mozilla/editor/libeditor/base/nsEditor.cpp index fd0895cccec..e73e9ec5820 100644 --- a/mozilla/editor/libeditor/base/nsEditor.cpp +++ b/mozilla/editor/libeditor/base/nsEditor.cpp @@ -164,6 +164,7 @@ nsEditor::nsEditor() , mAction(nsnull) , mDirection(eNone) , mInIMEMode(PR_FALSE) +, mIsIMEComposing(PR_FALSE) , mIMETextRangeList(nsnull) , mIMETextNode(nsnull) , mIMETextOffset(0) @@ -1946,6 +1947,7 @@ nsEditor::EndComposition(void) mIMETextOffset = 0; mIMEBufferLength = 0; mInIMEMode = PR_FALSE; + mIsIMEComposing = PR_FALSE; // notify editor observers of action NotifyEditorObservers(); @@ -4482,6 +4484,49 @@ nsEditor::DeleteSelectionAndCreateNode(const nsAString& aTag, /* Non-interface, protected methods */ +nsresult +nsEditor::GetIMEBufferLength(PRInt32* length) +{ + *length = mIMEBufferLength; + return NS_OK; +} + +void +nsEditor::SetIsIMEComposing(){ + // We set mIsIMEComposing according to mIMETextRangeList. + nsCOMPtr rangePtr; + PRUint16 listlen, type; + + mIsIMEComposing = PR_FALSE; + nsresult result = mIMETextRangeList->GetLength(&listlen); + if (NS_FAILED(result)) return; + + for (PRUint16 i = 0; i < listlen; i++) + { + result = mIMETextRangeList->Item(i, getter_AddRefs(rangePtr)); + if (NS_FAILED(result)) continue; + result = rangePtr->GetRangeType(&type); + if (NS_FAILED(result)) continue; + if ( type == nsIPrivateTextRange::TEXTRANGE_RAWINPUT || + type == nsIPrivateTextRange::TEXTRANGE_CONVERTEDTEXT || + type == nsIPrivateTextRange::TEXTRANGE_SELECTEDRAWTEXT || + type == nsIPrivateTextRange::TEXTRANGE_SELECTEDCONVERTEDTEXT ) + { + mIsIMEComposing = PR_TRUE; +#ifdef DEBUG_IME + printf("nsEditor::mIsIMEComposing = PR_TRUE\n"); +#endif + break; + } + } + return; +} + +PRBool +nsEditor::IsIMEComposing() { + return mIsIMEComposing; +} + NS_IMETHODIMP nsEditor::DeleteSelectionAndPrepareToCreateNode(nsCOMPtr &parentSelectedNode, PRInt32& offsetOfNewNode) { diff --git a/mozilla/editor/libeditor/base/nsEditor.h b/mozilla/editor/libeditor/base/nsEditor.h index c4348bf2f97..5a6ee34a7db 100644 --- a/mozilla/editor/libeditor/base/nsEditor.h +++ b/mozilla/editor/libeditor/base/nsEditor.h @@ -489,6 +489,9 @@ public: nsresult GetLastEditableNode(nsIDOMNode *aRoot, nsCOMPtr *outLastNode); #endif + nsresult GetIMEBufferLength(PRInt32* length); + PRBool IsIMEComposing(); /* test if IME is in composition state */ + void SetIsIMEComposing(); /* call this before |IsIMEComposing()| */ /** from html rules code - migration in progress */ static nsresult GetTagString(nsIDOMNode *aNode, nsAString& outString); @@ -564,11 +567,13 @@ protected: 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 + 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 + PRBool mIsIMEComposing; // is IME in composition state? + // This is different from mInIMEMode. see Bug 98434. // various listeners nsVoidArray* mActionListeners; // listens to all low level actions on the doc diff --git a/mozilla/editor/libeditor/base/nsEditorUtils.cpp b/mozilla/editor/libeditor/base/nsEditorUtils.cpp index f07ec717b5c..b9ac4359008 100644 --- a/mozilla/editor/libeditor/base/nsEditorUtils.cpp +++ b/mozilla/editor/libeditor/base/nsEditorUtils.cpp @@ -203,3 +203,47 @@ nsDOMSubtreeIterator::Init(nsIDOMNode* aNode) return mIter->Init(content); } +/****************************************************************************** + * some general purpose editor utils + *****************************************************************************/ + +PRBool +nsEditorUtils::IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 *aOffset) +{ + if (!aNode && !aParent) return PR_FALSE; + if (aNode == aParent) return PR_FALSE; + + nsCOMPtr parent, node = do_QueryInterface(aNode); + nsresult res; + + do + { + res = node->GetParentNode(getter_AddRefs(parent)); + if (NS_FAILED(res)) return PR_FALSE; + if (parent.get() == aParent) + { + if (aOffset) + { + nsCOMPtr pCon(do_QueryInterface(parent)); + nsCOMPtr cCon(do_QueryInterface(node)); + if (pCon && cCon) + { + pCon->IndexOf(cCon, *aOffset); + } + } + return PR_TRUE; + } + node = parent; + } while (parent); + + return PR_FALSE; +} + +PRBool +nsEditorUtils::IsLeafNode(nsIDOMNode *aNode) +{ + if (!aNode) return PR_FALSE; + PRBool hasChildren = PR_FALSE; + aNode->HasChildNodes(&hasChildren); + return !hasChildren; +} diff --git a/mozilla/editor/libeditor/base/nsEditorUtils.h b/mozilla/editor/libeditor/base/nsEditorUtils.h index c78918064b9..6c11b289269 100644 --- a/mozilla/editor/libeditor/base/nsEditorUtils.h +++ b/mozilla/editor/libeditor/base/nsEditorUtils.h @@ -263,4 +263,11 @@ struct DOMPoint }; +class nsEditorUtils +{ + public: + static PRBool IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 *aOffset = 0); + static PRBool IsLeafNode(nsIDOMNode *aNode); +}; + #endif // nsEditorUtils_h__ diff --git a/mozilla/editor/libeditor/base/nsIEditProperty.h b/mozilla/editor/libeditor/base/nsIEditProperty.h index 1440190016b..94e95a00762 100644 --- a/mozilla/editor/libeditor/base/nsIEditProperty.h +++ b/mozilla/editor/libeditor/base/nsIEditProperty.h @@ -167,6 +167,7 @@ public: static nsIAtom *cssVerticalAlign; static nsIAtom *cssWhitespace; static nsIAtom *cssWidth; + static nsIAtom *cssMozUserSelect; static nsIAtom *cssPxUnit; diff --git a/mozilla/editor/libeditor/base/nsSelectionState.cpp b/mozilla/editor/libeditor/base/nsSelectionState.cpp index c8f0db9265a..956d2598413 100644 --- a/mozilla/editor/libeditor/base/nsSelectionState.cpp +++ b/mozilla/editor/libeditor/base/nsSelectionState.cpp @@ -43,6 +43,7 @@ #include "nsISelection.h" #include "nsEditor.h" #include "nsLayoutCID.h" +#include "nsEditorUtils.h" static NS_DEFINE_CID(kCRangeCID, NS_RANGE_CID); @@ -308,6 +309,7 @@ nsRangeUpdater::SelAdjDeleteNode(nsIDOMNode *aNode) nsresult res = nsEditor::GetNodeLocation(aNode, address_of(parent), &offset); NS_ENSURE_SUCCESS(res, res); + // check for range endpoints that are after aNode and in the same parent for (i=0; iendNode.get() == parent) && (item->endOffset > offset)) item->endOffset--; } - // MOOSE: also check inside of aNode, expensive. But in theory, we shouldn't - // actually hit this case in the usage i forsee for this. + + // check for range endpoints that are in aNode + if (item->startNode == aNode) + { + item->startNode = parent; + item->startOffset = offset; + } + if (item->endNode == aNode) + { + item->endNode = parent; + item->endOffset = offset; + } + + // check for range endpoints that are in descendants of aNode + nsCOMPtr oldStart; + if (nsEditorUtils::IsDescendantOf(item->startNode, aNode)) + { + oldStart = item->startNode; // save for efficiency hack below. + item->startNode = parent; + item->startOffset = offset; + } + + // avoid having to call IsDescendantOf() for common case of range startnode == range endnode. + if ((item->endNode == oldStart) || nsEditorUtils::IsDescendantOf(item->endNode, aNode)) + { + item->endNode = parent; + item->endOffset = offset; + } + return NS_OK; } @@ -427,6 +456,11 @@ nsRangeUpdater::SelAdjJoinNodes(nsIDOMNode *aLeftNode, item->startOffset += aOldLeftNodeLength; if (item->endNode.get() == aRightNode) item->endOffset += aOldLeftNodeLength; + // adjust endpoints in aLeftNode + if (item->startNode.get() == aLeftNode) + item->startNode = aRightNode; + if (item->endNode.get() == aLeftNode) + item->endNode = aRightNode; } return NS_OK; diff --git a/mozilla/editor/libeditor/html/nsEditProperty.cpp b/mozilla/editor/libeditor/html/nsEditProperty.cpp index a40220f51ed..9ad88c3fc8f 100644 --- a/mozilla/editor/libeditor/html/nsEditProperty.cpp +++ b/mozilla/editor/libeditor/html/nsEditProperty.cpp @@ -144,6 +144,7 @@ nsIAtom * nsIEditProperty::cssTextDecoration; nsIAtom * nsIEditProperty::cssVerticalAlign; nsIAtom * nsIEditProperty::cssWhitespace; nsIAtom * nsIEditProperty::cssWidth; +nsIAtom * nsIEditProperty::cssMozUserSelect; nsIAtom * nsIEditProperty::cssPxUnit; @@ -282,6 +283,7 @@ nsEditProperty::nsEditProperty() nsIEditProperty::cssVerticalAlign = NS_NewAtom("vertical-align"); nsIEditProperty::cssWhitespace = NS_NewAtom("white-space"); nsIEditProperty::cssWidth = NS_NewAtom("width"); + nsIEditProperty::cssMozUserSelect = NS_NewAtom("-moz-user-select"); nsIEditProperty::cssPxUnit = NS_NewAtom("px"); @@ -394,6 +396,7 @@ nsEditProperty::~nsEditProperty() NS_IF_RELEASE(nsIEditProperty::cssVerticalAlign); NS_IF_RELEASE(nsIEditProperty::cssWhitespace); NS_IF_RELEASE(nsIEditProperty::cssWidth); + NS_IF_RELEASE(nsIEditProperty::cssMozUserSelect); NS_IF_RELEASE(nsIEditProperty::cssPxUnit); NS_IF_RELEASE(nsIEditProperty::cssEmUnit); diff --git a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp index d9eabe31566..f8b298d9c36 100644 --- a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp @@ -477,7 +477,7 @@ nsHTMLEditor::InsertHTMLWithCharsetAndContext(const nsAString & aInputString, { // if we had to insert something higher up in the paste heirarchy, we want to // skip any further paste nodes that descend from that. Else we will paste twice. - if (nsHTMLEditUtils::IsDescendantOf(curNode, insertedContextParent)) + if (nsEditorUtils::IsDescendantOf(curNode, insertedContextParent)) continue; } @@ -2425,7 +2425,7 @@ nsHTMLEditor::ReplaceOrphanedStructure(PRBool aEnd, { endpoint = GetArrayEndpoint(aEnd, aNodeArray); if (!endpoint) break; - if (nsHTMLEditUtils::IsDescendantOf(endpoint, replaceNode)) + if (nsEditorUtils::IsDescendantOf(endpoint, replaceNode)) aNodeArray.RemoveObject(endpoint); else break; diff --git a/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp b/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp index f7fe9a87583..243ce59519f 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp @@ -459,27 +459,13 @@ nsHTMLEditRules::AfterEditInner(PRInt32 action, nsIEditor::EDirection aDirection res = AdjustWhitespace(selection); if (NS_FAILED(res)) return res; - // also do this for original selection endpoints. The checks for the remembered - // selection endpoints are a performance fidgit. Otherwise - // nsRangeUpdater::SelAdjDeleteNode() would have to do much more expensive - // work (see comment in that routine in nsSelection.cpp) - nsCOMPtr bodyNode; - PRInt32 unused; - res = mHTMLEditor->GetRootElement(getter_AddRefs(bodyNode)); - if (NS_FAILED(res)) return res; - if (nsHTMLEditUtils::IsDescendantOf(mRangeItem.startNode, bodyNode, &unused)) - { - nsWSRunObject(mHTMLEditor, mRangeItem.startNode, mRangeItem.startOffset).AdjustWhitespace(); - } + // also do this for original selection endpoints. + nsWSRunObject(mHTMLEditor, mRangeItem.startNode, mRangeItem.startOffset).AdjustWhitespace(); // we only need to handle old selection endpoint if it was different from start if ((mRangeItem.startNode != mRangeItem.endNode) || (mRangeItem.startOffset != mRangeItem.endOffset)) { - if (nsHTMLEditUtils::IsDescendantOf(mRangeItem.endNode, bodyNode, &unused)) - { - nsWSRunObject(mHTMLEditor, mRangeItem.endNode, mRangeItem.endOffset).AdjustWhitespace(); - } + nsWSRunObject(mHTMLEditor, mRangeItem.endNode, mRangeItem.endOffset).AdjustWhitespace(); } - } // if we created a new block, make sure selection lands in it @@ -1693,7 +1679,7 @@ nsHTMLEditRules::SplitMailCites(nsISelection *aSelection, PRBool aPlaintext, PRB { // ok, we are just before a break. is it inside the mailquote? PRInt32 unused; - if (nsHTMLEditUtils::IsDescendantOf(visNode, citeNode, &unused)) + if (nsEditorUtils::IsDescendantOf(visNode, citeNode, &unused)) { // it is. so lets reset our selection to be just after it. res = mHTMLEditor->GetNodeLocation(visNode, address_of(selNode), &selOffset); @@ -1874,7 +1860,12 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection, so--; eo--; } - return nsWSRunObject::PrepareToDeleteRange(mHTMLEditor, address_of(visNode), &so, address_of(visNode), &eo); + res = nsWSRunObject::PrepareToDeleteRange(mHTMLEditor, address_of(visNode), &so, address_of(visNode), &eo); + if (NS_FAILED(res)) return res; + nsCOMPtr nodeAsText(do_QueryInterface(visNode)); + res = mHTMLEditor->DeleteText(nodeAsText,so,1); + *aHandled = PR_TRUE; + return res; } else if ( (wsType==nsWSRunObject::eSpecial) || (wsType==nsWSRunObject::eBreak) || @@ -2240,8 +2231,8 @@ nsHTMLEditRules::JoinBlocks(nsCOMPtr *aLeftBlock, // the other lists' items. Note that it is ok for them to be descendants // of the other lists themselves, which is the usual case for sublists // in our impllementation. - if (!nsHTMLEditUtils::IsDescendantOf(leftList, *aRightBlock, &theOffset) && - !nsHTMLEditUtils::IsDescendantOf(rightList, *aLeftBlock, &theOffset)) + if (!nsEditorUtils::IsDescendantOf(leftList, *aRightBlock, &theOffset) && + !nsEditorUtils::IsDescendantOf(rightList, *aLeftBlock, &theOffset)) { *aLeftBlock = leftList; *aRightBlock = rightList; @@ -2260,7 +2251,7 @@ nsHTMLEditRules::JoinBlocks(nsCOMPtr *aLeftBlock, // theOffset below is where you find yourself in aRightBlock when you traverse upwards // from aLeftBlock - if (nsHTMLEditUtils::IsDescendantOf(*aLeftBlock, *aRightBlock, &rightOffset)) + if (nsEditorUtils::IsDescendantOf(*aLeftBlock, *aRightBlock, &rightOffset)) { // tricky case. left block is inside right block. // Do ws adjustment. This just destroys non-visible ws at boundaries we will be joining. @@ -2297,7 +2288,7 @@ nsHTMLEditRules::JoinBlocks(nsCOMPtr *aLeftBlock, } // theOffset below is where you find yourself in aLeftBlock when you traverse upwards // from aRightBlock - else if (nsHTMLEditUtils::IsDescendantOf(*aRightBlock, *aLeftBlock, &leftOffset)) + else if (nsEditorUtils::IsDescendantOf(*aRightBlock, *aLeftBlock, &leftOffset)) { // tricky case. right block is inside left block. // Do ws adjustment. This just destroys non-visible ws at boundaries we will be joining. @@ -2643,7 +2634,7 @@ nsHTMLEditRules::WillMakeList(nsISelection *aSelection, res = mHTMLEditor->GetTagString(curNode, existingListStr); ToLowerCase(existingListStr); // do we have a curList already? - if (curList && !nsHTMLEditUtils::IsDescendantOf(curNode, curList)) + if (curList && !nsEditorUtils::IsDescendantOf(curNode, curList)) { // move all of our children into curList. // cheezy way to do it: move whole list and then @@ -2678,7 +2669,7 @@ nsHTMLEditRules::WillMakeList(nsISelection *aSelection, // list item is in wrong type of list. // if we dont have a curList, split the old list // and make a new list of correct type. - if (!curList || nsHTMLEditUtils::IsDescendantOf(curNode, curList)) + if (!curList || nsEditorUtils::IsDescendantOf(curNode, curList)) { res = mHTMLEditor->SplitNode(curParent, offset, getter_AddRefs(newBlock)); if (NS_FAILED(res)) return res; @@ -3505,7 +3496,7 @@ nsHTMLEditRules::WillOutdent(nsISelection *aSelection, PRBool *aCancel, PRBool * if (curBlockQuote) { // if so, is this node a descendant? - if (nsHTMLEditUtils::IsDescendantOf(curNode, curBlockQuote)) + if (nsEditorUtils::IsDescendantOf(curNode, curBlockQuote)) { lastBQChild = curNode; continue; // then we dont need to do anything different for this node @@ -3614,7 +3605,7 @@ nsHTMLEditRules::WillOutdent(nsISelection *aSelection, PRBool *aCancel, PRBool * nsCOMPtr sNode; PRInt32 sOffset; mHTMLEditor->GetStartNodeAndOffset(aSelection, address_of(sNode), &sOffset); - if ((sNode == rememberedLeftBQ) || nsHTMLEditUtils::IsDescendantOf(sNode, rememberedLeftBQ)) + if ((sNode == rememberedLeftBQ) || nsEditorUtils::IsDescendantOf(sNode, rememberedLeftBQ)) { // selection is inside rememberedLeftBQ - push it past it. nsEditor::GetNodeLocation(rememberedLeftBQ, address_of(sNode), &sOffset); @@ -3623,7 +3614,7 @@ nsHTMLEditRules::WillOutdent(nsISelection *aSelection, PRBool *aCancel, PRBool * } // and pull selection before beginning of rememberedRightBQ mHTMLEditor->GetStartNodeAndOffset(aSelection, address_of(sNode), &sOffset); - if ((sNode == rememberedRightBQ) || nsHTMLEditUtils::IsDescendantOf(sNode, rememberedRightBQ)) + if ((sNode == rememberedRightBQ) || nsEditorUtils::IsDescendantOf(sNode, rememberedRightBQ)) { // selection is inside rememberedRightBQ - push it before it. nsEditor::GetNodeLocation(rememberedRightBQ, address_of(sNode), &sOffset); @@ -5984,20 +5975,46 @@ nsHTMLEditRules::ReturnInListItem(nsISelection *aSelection, res = CreateMozBR(prevItem, 0, address_of(brNode)); if (NS_FAILED(res)) return res; } - else { + else + { res = mHTMLEditor->IsEmptyNode(aListItem, &bIsEmptyNode, PR_TRUE); if (NS_FAILED(res)) return res; - if (bIsEmptyNode) { + if (bIsEmptyNode) + { nsCOMPtr brNode; res = mHTMLEditor->CopyLastEditableChildStyles(prevItem, aListItem, getter_AddRefs(brNode)); if (NS_FAILED(res)) return res; - if (brNode) { + if (brNode) + { nsCOMPtr brParent; PRInt32 offset; res = nsEditor::GetNodeLocation(brNode, address_of(brParent), &offset); return aSelection->Collapse(brParent, offset); } } + else + { + nsWSRunObject wsObj(mHTMLEditor, aListItem, 0); + nsCOMPtr visNode; + PRInt32 visOffset = 0; + PRInt16 wsType; + res = wsObj.NextVisibleNode(aListItem, 0, address_of(visNode), &visOffset, &wsType); + if (NS_FAILED(res)) return res; + if ( (wsType==nsWSRunObject::eSpecial) || + (wsType==nsWSRunObject::eBreak) || + nsHTMLEditUtils::IsHR(visNode) ) + { + nsCOMPtr parent; + PRInt32 offset; + res = nsEditor::GetNodeLocation(visNode, address_of(parent), &offset); + if (NS_FAILED(res)) return res; + return aSelection->Collapse(parent, offset); + } + else + { + return aSelection->Collapse(visNode, visOffset); + } + } } } res = aSelection->Collapse(aListItem,0); @@ -6163,7 +6180,7 @@ nsHTMLEditRules::RemoveBlockStyle(nsCOMArray& arrayOfNodes) if (curBlock) { // if so, is this node a descendant? - if (nsHTMLEditUtils::IsDescendantOf(curNode, curBlock)) + if (nsEditorUtils::IsDescendantOf(curNode, curBlock)) { lastNode = curNode; continue; // then we dont need to do anything different for this node @@ -7162,7 +7179,7 @@ nsHTMLEditRules::SelectionEndpointInNode(nsIDOMNode *aNode, PRBool *aResult) *aResult = PR_TRUE; return NS_OK; } - if (nsHTMLEditUtils::IsDescendantOf(startParent, aNode)) + if (nsEditorUtils::IsDescendantOf(startParent, aNode)) { *aResult = PR_TRUE; return NS_OK; @@ -7177,7 +7194,7 @@ nsHTMLEditRules::SelectionEndpointInNode(nsIDOMNode *aNode, PRBool *aResult) *aResult = PR_TRUE; return NS_OK; } - if (nsHTMLEditUtils::IsDescendantOf(endParent, aNode)) + if (nsEditorUtils::IsDescendantOf(endParent, aNode)) { *aResult = PR_TRUE; return NS_OK; diff --git a/mozilla/editor/libeditor/html/nsHTMLEditUtils.cpp b/mozilla/editor/libeditor/html/nsHTMLEditUtils.cpp index 5b9f6813e7f..ded7b69e454 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditUtils.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLEditUtils.cpp @@ -394,47 +394,6 @@ nsHTMLEditUtils::IsFormWidget(nsIDOMNode *node) return PR_FALSE; } -PRBool -nsHTMLEditUtils::IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 *aOffset) -{ - if (!aNode && !aParent) return PR_FALSE; - if (aNode == aParent) return PR_FALSE; - - nsCOMPtr parent, node = do_QueryInterface(aNode); - nsresult res; - - do - { - res = node->GetParentNode(getter_AddRefs(parent)); - if (NS_FAILED(res)) return PR_FALSE; - if (parent.get() == aParent) - { - if (aOffset) - { - nsCOMPtr pCon(do_QueryInterface(parent)); - nsCOMPtr cCon(do_QueryInterface(node)); - if (pCon && cCon) - { - pCon->IndexOf(cCon, *aOffset); - } - } - return PR_TRUE; - } - node = parent; - } while (parent); - - return PR_FALSE; -} - -PRBool -nsHTMLEditUtils::IsLeafNode(nsIDOMNode *aNode) -{ - if (!aNode) return PR_FALSE; - PRBool hasChildren = PR_FALSE; - aNode->HasChildNodes(&hasChildren); - return !hasChildren; -} - PRBool nsHTMLEditUtils::SupportsAlignAttr(nsIDOMNode * aNode) { diff --git a/mozilla/editor/libeditor/html/nsHTMLEditUtils.h b/mozilla/editor/libeditor/html/nsHTMLEditUtils.h index 694b46b112b..52cc7dd0b92 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditUtils.h +++ b/mozilla/editor/libeditor/html/nsHTMLEditUtils.h @@ -75,8 +75,6 @@ public: static PRBool IsMozDiv(nsIDOMNode *aNode); static PRBool IsMailCite(nsIDOMNode *aNode); static PRBool IsFormWidget(nsIDOMNode *aNode); - static PRBool IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 *aOffset = 0); - static PRBool IsLeafNode(nsIDOMNode *aNode); static PRBool SupportsAlignAttr(nsIDOMNode *aNode); }; diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp index 29445e1e758..899262fe842 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp @@ -3947,7 +3947,61 @@ nsHTMLEditor::GetEmbeddedObjects(nsISupportsArray** aNodeList) #pragma mark - #endif -// Undo, Redo, Cut, CanCut, Copy, CanCopy, all inherited from nsPlaintextEditor +NS_IMETHODIMP nsHTMLEditor::DeleteNode(nsIDOMNode * aNode) +{ + nsCOMPtr selectAllNode = FindUserSelectAllNode(aNode); + + if (selectAllNode) + { + return nsEditor::DeleteNode(selectAllNode); + } + return nsEditor::DeleteNode(aNode); +} + +NS_IMETHODIMP nsHTMLEditor::DeleteText(nsIDOMCharacterData *aTextNode, + PRUint32 aOffset, + PRUint32 aLength) +{ + nsCOMPtr selectAllNode = FindUserSelectAllNode(aTextNode); + + if (selectAllNode) + { + return nsEditor::DeleteNode(selectAllNode); + } + return nsEditor::DeleteText(aTextNode, aOffset, aLength); +} + + +#ifdef XP_MAC +#pragma mark - +#pragma mark support utils +#pragma mark - +#endif + +/* This routine examines aNode and it's ancestors looking for any node which has the + -moz-user-select: all style lit. Return the ighest such ancestor. */ +nsCOMPtr nsHTMLEditor::FindUserSelectAllNode(nsIDOMNode *aNode) +{ + nsCOMPtr resultNode; // starts out empty + nsCOMPtr node = aNode; + + // retrieve the computed style of -moz-user-select for aNode + nsAutoString mozUserSelectValue; + while (node) + { + mHTMLCSSUtils->GetComputedProperty(node, nsIEditProperty::cssMozUserSelect, mozUserSelectValue); + if (!mozUserSelectValue.Equals(NS_LITERAL_STRING("all"))) + { + return resultNode; + } + resultNode = node; + nsCOMPtr tmp; + node->GetParentNode(getter_AddRefs(tmp)); + node = tmp; + } + + return resultNode; +} static nsresult SetSelectionAroundHeadChildren(nsCOMPtr aSelection, nsWeakPtr aDocWeak) { @@ -5186,7 +5240,7 @@ nsHTMLEditor::GetFirstEditableLeaf( nsIDOMNode *aNode, nsCOMPtr *aOu nsCOMPtr child; nsresult res = NS_OK; child = GetLeftmostChild(aNode); - while (child && (!IsEditable(child) || !nsHTMLEditUtils::IsLeafNode(child))) + while (child && (!IsEditable(child) || !nsEditorUtils::IsLeafNode(child))) { nsCOMPtr tmp; res = GetNextHTMLNode(child, address_of(tmp)); @@ -5194,7 +5248,7 @@ nsHTMLEditor::GetFirstEditableLeaf( nsIDOMNode *aNode, nsCOMPtr *aOu if (!tmp) return NS_ERROR_FAILURE; // only accept nodes that are descendants of aNode - if (nsHTMLEditUtils::IsDescendantOf(tmp, aNode)) + if (nsEditorUtils::IsDescendantOf(tmp, aNode)) child = tmp; else { @@ -5220,7 +5274,7 @@ nsHTMLEditor::GetLastEditableLeaf( nsIDOMNode *aNode, nsCOMPtr *aOut nsCOMPtr child; nsresult res = NS_OK; child = GetRightmostChild(aNode, PR_FALSE); - while (child && (!IsEditable(child) || !nsHTMLEditUtils::IsLeafNode(child))) + while (child && (!IsEditable(child) || !nsEditorUtils::IsLeafNode(child))) { nsCOMPtr tmp; res = GetPriorHTMLNode(child, address_of(tmp)); @@ -5228,7 +5282,7 @@ nsHTMLEditor::GetLastEditableLeaf( nsIDOMNode *aNode, nsCOMPtr *aOut if (!tmp) return NS_ERROR_FAILURE; // only accept nodes that are descendants of aNode - if (nsHTMLEditUtils::IsDescendantOf(tmp, aNode)) + if (nsEditorUtils::IsDescendantOf(tmp, aNode)) child = tmp; else { @@ -5413,7 +5467,7 @@ nsHTMLEditor::IsEmptyNodeImpl( nsIDOMNode *aNode, return NS_OK; } - PRBool isEmptyNode; + PRBool isEmptyNode = PR_TRUE; res = IsEmptyNodeImpl(node, &isEmptyNode, aSingleBRDoesntCount, aListOrCellNotEmpty, aSafeToAskFrames, aSeenBR); if (NS_FAILED(res)) return res; diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.h b/mozilla/editor/libeditor/html/nsHTMLEditor.h index cb9c0001f1f..76236378276 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.h +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.h @@ -416,6 +416,11 @@ public: virtual PRBool NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2); + NS_IMETHODIMP DeleteNode(nsIDOMNode * aNode); + NS_IMETHODIMP DeleteText(nsIDOMCharacterData *aTextNode, + PRUint32 aOffset, + PRUint32 aLength); + /* ------------ nsICSSLoaderObserver -------------- */ NS_IMETHOD StyleSheetLoaded(nsICSSStyleSheet*aSheet, PRBool aNotify); @@ -425,6 +430,7 @@ public: nsCOMPtr *ioParent, PRInt32 *ioOffset, PRBool aNoEmptyNodes); + nsCOMPtr FindUserSelectAllNode(nsIDOMNode *aNode); /** returns the absolute position of the end points of aSelection diff --git a/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp b/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp index eff1009b673..06dbcbc125c 100644 --- a/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp +++ b/mozilla/editor/libeditor/text/nsPlaintextEditor.cpp @@ -134,7 +134,6 @@ nsPlaintextEditor::nsPlaintextEditor() : nsEditor() , mIgnoreSpuriousDragEvent(PR_FALSE) , mRules(nsnull) -, mIsComposing(PR_FALSE) , mWrapToWindow(PR_FALSE) , mWrapColumn(0) , mMaxTextLength(-1) @@ -1974,6 +1973,8 @@ nsPlaintextEditor::SetCompositionString(const nsAString& aCompositionString, nsI { nsAutoPlaceHolderBatch batch(this, gIMETxnName); + SetIsIMEComposing(); // We set mIsIMEComposing properly. + result = InsertText(aCompositionString); mIMEBufferLength = aCompositionString.Length(); diff --git a/mozilla/editor/libeditor/text/nsPlaintextEditor.h b/mozilla/editor/libeditor/text/nsPlaintextEditor.h index dbc1cac4543..8143ca477bb 100644 --- a/mozilla/editor/libeditor/text/nsPlaintextEditor.h +++ b/mozilla/editor/libeditor/text/nsPlaintextEditor.h @@ -251,7 +251,6 @@ protected: nsCOMPtr mCompositionListenerP; nsCOMPtr mDragListenerP; nsCOMPtr mFocusListenerP; - PRBool mIsComposing; PRBool mWrapToWindow; PRInt32 mWrapColumn; PRInt32 mMaxTextLength; diff --git a/mozilla/editor/libeditor/text/nsTextEditRules.cpp b/mozilla/editor/libeditor/text/nsTextEditRules.cpp index d7a3e3b35bc..07835dd23b9 100644 --- a/mozilla/editor/libeditor/text/nsTextEditRules.cpp +++ b/mozilla/editor/libeditor/text/nsTextEditRules.cpp @@ -1304,7 +1304,8 @@ nsTextEditRules::TruncateInsertionIfNeeded(nsISelection *aSelection, nsresult res = NS_OK; *aOutString = *aInString; - if ((-1 != aMaxLength) && (mFlags & nsIPlaintextEditor::eEditorPlaintextMask)) + if ((-1 != aMaxLength) && (mFlags & nsIPlaintextEditor::eEditorPlaintextMask) + && !mEditor->IsIMEComposing() ) { // Get the current text length. // Get the length of inString. @@ -1313,6 +1314,8 @@ nsTextEditRules::TruncateInsertionIfNeeded(nsISelection *aSelection, // Subtract the length of the selection from the len(doc) // since we'll delete the selection on insert. // This is resultingDocLength. + // Get old length of IME composing string + // which will be replaced by new one. // If (resultingDocLength) is at or over max, cancel the insert // If (resultingDocLength) + (length of input) > max, // set aOutString to subset of inString so length = max @@ -1324,7 +1327,10 @@ nsTextEditRules::TruncateInsertionIfNeeded(nsISelection *aSelection, if (NS_FAILED(res)) { return res; } PRInt32 selectionLength = end-start; if (selectionLength<0) { selectionLength *= (-1); } - PRInt32 resultingDocLength = docLength - selectionLength; + PRInt32 oldCompStrLength; + res = mEditor->GetIMEBufferLength(&oldCompStrLength); + if (NS_FAILED(res)) { return res; } + PRInt32 resultingDocLength = docLength - selectionLength - oldCompStrLength; if (resultingDocLength >= aMaxLength) { aOutString->SetLength(0);