divElem = do_QueryInterface(curDiv);
nsAutoString attr; attr.AssignWithConversion("align");
@@ -4918,6 +4951,9 @@ nsHTMLEditRules::MakeBlockquote(nsISupportsArray *arrayOfNodes)
if (NS_FAILED(res)) return res;
res = mHTMLEditor->CreateNode(quoteType, curParent, offset, getter_AddRefs(curBlock));
if (NS_FAILED(res)) return res;
+ // remember our new block for postprocessing
+ mNewBlock = curBlock;
+ // note: doesn't matter if we set mNewBlock multiple times.
}
PRUint32 blockLen;
@@ -5179,6 +5215,9 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
if (NS_FAILED(res)) return res;
res = mHTMLEditor->CreateNode(*aBlockTag, curParent, offset, getter_AddRefs(curBlock));
if (NS_FAILED(res)) return res;
+ // remember our new block for postprocessing
+ mNewBlock = curBlock;
+ // note: doesn't matter if we set mNewBlock multiple times.
}
// if curNode is a Break, replace it with a return if we are going to
@@ -5397,6 +5436,111 @@ nsHTMLEditRules::AdjustWhitespace(nsISelection *aSelection)
return nsWSRunObject(mHTMLEditor, selNode, selOffset).AdjustWhitespace();
}
+nsresult
+nsHTMLEditRules::PinSelectionToNewBlock(nsISelection *aSelection)
+{
+ if (!aSelection) return NS_ERROR_NULL_POINTER;
+ PRBool bCollapsed;
+ nsresult res = aSelection->GetIsCollapsed(&bCollapsed);
+ if (NS_FAILED(res)) return res;
+ if (!bCollapsed) return res;
+
+ // get the (collapsed) selection location
+ nsCOMPtr selNode, temp;
+ PRInt32 selOffset;
+ res = mHTMLEditor->GetStartNodeAndOffset(aSelection, address_of(selNode), &selOffset);
+ if (NS_FAILED(res)) return res;
+ temp = selNode;
+
+ // use ranges and mRangeHelper to compare sel point to new block
+ nsCOMPtr range = do_CreateInstance(kRangeCID);
+ res = range->SetStart(selNode, selOffset);
+ if (NS_FAILED(res)) return res;
+ res = range->SetEnd(selNode, selOffset);
+ if (NS_FAILED(res)) return res;
+ nsCOMPtr block (do_QueryInterface(mNewBlock));
+ if (!block) return NS_ERROR_NO_INTERFACE;
+ PRBool nodeBefore, nodeAfter;
+ res = mHTMLEditor->mRangeHelper->CompareNodeToRange(block, range, &nodeBefore, &nodeAfter);
+ if (NS_FAILED(res)) return res;
+
+ if (nodeBefore && nodeAfter)
+ return NS_OK; // selection is inside block
+ else if (nodeBefore)
+ {
+ // selection is after block. put at end of block.
+ nsCOMPtr tmp = mNewBlock;
+ mHTMLEditor->GetLastEditableChild(mNewBlock, address_of(tmp));
+ PRUint32 endPoint;
+ if (mHTMLEditor->IsTextNode(tmp) || mHTMLEditor->IsContainer(tmp))
+ {
+ res = nsEditor::GetLengthOfDOMNode(tmp, endPoint);
+ if (NS_FAILED(res)) return res;
+ }
+ else
+ {
+ nsCOMPtr tmp2;
+ res = nsEditor::GetNodeLocation(tmp, address_of(tmp2), (PRInt32*)&endPoint);
+ if (NS_FAILED(res)) return res;
+ tmp = tmp2;
+ endPoint++; // want to be after this node
+ }
+ return aSelection->Collapse(tmp, (PRInt32)endPoint);
+ }
+ else
+ {
+ // selection is before block. put at start of block.
+ nsCOMPtr tmp = mNewBlock;
+ mHTMLEditor->GetFirstEditableChild(mNewBlock, address_of(tmp));
+ PRInt32 offset;
+ if (!(mHTMLEditor->IsTextNode(tmp) || mHTMLEditor->IsContainer(tmp)))
+ {
+ nsCOMPtr tmp2;
+ res = nsEditor::GetNodeLocation(tmp, address_of(tmp2), &offset);
+ if (NS_FAILED(res)) return res;
+ tmp = tmp2;
+ }
+ return aSelection->Collapse(tmp, 0);
+ }
+}
+
+nsresult
+nsHTMLEditRules::CheckInterlinePosition(nsISelection *aSelection)
+{
+ if (!aSelection) return NS_ERROR_NULL_POINTER;
+ nsCOMPtr selection(aSelection);
+ nsCOMPtr selPriv(do_QueryInterface(selection));
+
+ // if the selection isn't collapsed, do nothing.
+ PRBool bCollapsed;
+ nsresult res = aSelection->GetIsCollapsed(&bCollapsed);
+ if (NS_FAILED(res)) return res;
+ if (!bCollapsed) return res;
+
+ // get the (collapsed) selection location
+ nsCOMPtr selNode, node;
+ PRInt32 selOffset;
+ res = mHTMLEditor->GetStartNodeAndOffset(aSelection, address_of(selNode), &selOffset);
+ if (NS_FAILED(res)) return res;
+
+ // are we after a block? If so try set caret to following content
+ mHTMLEditor->GetPriorHTMLSibling(selNode, selOffset, address_of(node));
+ if (node && IsBlockNode(node))
+ {
+ selPriv->SetInterlinePosition(PR_TRUE);
+ return NS_OK;
+ }
+
+ // are we before a block? If so try set caret to prior content
+ mHTMLEditor->GetNextHTMLSibling(selNode, selOffset, address_of(node));
+ if (node && IsBlockNode(node))
+ {
+ selPriv->SetInterlinePosition(PR_FALSE);
+ return NS_OK;
+ }
+ return NS_OK;
+}
+
nsresult
nsHTMLEditRules::AdjustSelection(nsISelection *aSelection, nsIEditor::EDirection aAction)
{
diff --git a/mozilla/editor/base/nsHTMLEditRules.h b/mozilla/editor/base/nsHTMLEditRules.h
index 6738407d515..e9b9c791926 100644
--- a/mozilla/editor/base/nsHTMLEditRules.h
+++ b/mozilla/editor/base/nsHTMLEditRules.h
@@ -179,6 +179,8 @@ protected:
nsresult RemoveListStructure(nsIDOMNode *aList);
nsresult AdjustSpecialBreaks(PRBool aSafeToAskFrames = PR_FALSE);
nsresult AdjustWhitespace(nsISelection *aSelection);
+ nsresult PinSelectionToNewBlock(nsISelection *aSelection);
+ nsresult CheckInterlinePosition(nsISelection *aSelection);
nsresult AdjustSelection(nsISelection *aSelection, nsIEditor::EDirection aAction);
nsresult FindNearSelectableNode(nsIDOMNode *aSelNode,
PRInt32 aSelOffset,
@@ -202,6 +204,7 @@ protected:
PRBool mReturnInEmptyLIKillsList;
nsCOMPtr mUtilRange;
PRUint32 mJoinOffset; // need to remember an int across willJoin/didJoin...
+ nsCOMPtr mNewBlock;
};
diff --git a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp
index be450f456b2..4aed039c590 100644
--- a/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/mozilla/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -357,9 +357,14 @@ nsresult nsHTMLEditor::InsertHTMLWithCharsetAndContext(const nsAReadableString &
// Loop over the node list and paste the nodes:
PRBool bDidInsert = PR_FALSE;
- nsCOMPtr lastInsertNode, insertedContextParent;
+ nsCOMPtr parentBlock, lastInsertNode, insertedContextParent;
PRUint32 listCount, j;
nodeList->Count(&listCount);
+ if (IsBlockNode(parentNode))
+ parentBlock = parentNode;
+ else
+ parentBlock = GetBlockNodeParent(parentNode);
+
for (j=0; j isupports = dont_AddRef(nodeList->ElementAt(j));
@@ -425,8 +430,26 @@ nsresult nsHTMLEditor::InsertHTMLWithCharsetAndContext(const nsAReadableString &
curNode->GetFirstChild(getter_AddRefs(child));
}
}
+ // check for pre's going into pre's.
+ else if (nsHTMLEditUtils::IsPre(parentBlock) && nsHTMLEditUtils::IsPre(curNode))
+ {
+ nsCOMPtr child, tmp;
+ curNode->GetFirstChild(getter_AddRefs(child));
+ while (child)
+ {
+ res = InsertNodeAtPoint(child, address_of(parentNode), &offsetOfNewNode, PR_TRUE);
+ if (NS_SUCCEEDED(res))
+ {
+ bDidInsert = PR_TRUE;
+ lastInsertNode = child;
+ offsetOfNewNode++;
+ }
+ curNode->GetFirstChild(getter_AddRefs(child));
+ }
+ }
else
{
+
// try to insert
res = InsertNodeAtPoint(curNode, address_of(parentNode), &offsetOfNewNode, PR_TRUE);
if (NS_SUCCEEDED(res))
diff --git a/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp b/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp
index 0392ac4f6fe..dcffe5abd7c 100644
--- a/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp
+++ b/mozilla/editor/libeditor/html/nsHTMLEditRules.cpp
@@ -400,6 +400,13 @@ nsHTMLEditRules::AfterEditInner(PRInt32 action, nsIEditor::EDirection aDirection
if (NS_FAILED(res)) return res;
}
+ // if we created a new block, make sure selection lands in it
+ if (mNewBlock)
+ {
+ res = PinSelectionToNewBlock(selection);
+ mNewBlock = 0;
+ }
+
// adjust selection for insert text, html paste, and delete actions
if ((action == nsEditor::kOpInsertText) ||
(action == nsEditor::kOpInsertIMEText) ||
@@ -410,10 +417,15 @@ nsHTMLEditRules::AfterEditInner(PRInt32 action, nsIEditor::EDirection aDirection
res = AdjustSelection(selection, aDirection);
if (NS_FAILED(res)) return res;
}
+
}
// detect empty doc
res = CreateBogusNodeIfNeeded(selection);
+
+ // adjust selection HINT if needed
+ if (NS_FAILED(res)) return res;
+ res = CheckInterlinePosition(selection);
return res;
}
@@ -1841,135 +1853,140 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
}
if (endNode.get() != startNode.get())
{
- // block parents the same? use default deletion
- nsCOMPtr leftParent;
- nsCOMPtr rightParent;
- if (IsBlockNode(startNode))
- leftParent = startNode;
- else
- leftParent = mHTMLEditor->GetBlockNodeParent(startNode);
- if (IsBlockNode(endNode))
- rightParent = endNode;
- else
- rightParent = mHTMLEditor->GetBlockNodeParent(endNode);
- if (leftParent.get() == rightParent.get()) return NS_OK;
-
- // deleting across blocks
- // are the blocks of same type?
-
- // are the blocks siblings?
- nsCOMPtr leftBlockParent;
- nsCOMPtr rightBlockParent;
- leftParent->GetParentNode(getter_AddRefs(leftBlockParent));
- rightParent->GetParentNode(getter_AddRefs(rightBlockParent));
-
- // MOOSE: this could conceivably screw up a table.. fix me.
- if ( (leftBlockParent.get() == rightBlockParent.get())
- && (mHTMLEditor->NodesSameType(leftParent, rightParent)) )
{
- if (nsHTMLEditUtils::IsParagraph(leftParent))
- {
- // first delete the selection
- *aHandled = PR_TRUE;
- res = mHTMLEditor->DeleteSelectionImpl(aAction);
- if (NS_FAILED(res)) return res;
- // then join para's, insert break
- res = mHTMLEditor->JoinNodeDeep(leftParent,rightParent,address_of(selNode),&selOffset);
- if (NS_FAILED(res)) return res;
- // fix up selection
- res = aSelection->Collapse(selNode,selOffset);
- return res;
- }
- if (nsHTMLEditUtils::IsListItem(leftParent)
- || nsHTMLEditUtils::IsHeader(leftParent))
- {
- // first delete the selection
- *aHandled = PR_TRUE;
- res = mHTMLEditor->DeleteSelectionImpl(aAction);
- if (NS_FAILED(res)) return res;
- // join blocks
- res = mHTMLEditor->JoinNodeDeep(leftParent,rightParent,address_of(selNode),&selOffset);
- if (NS_FAILED(res)) return res;
- // fix up selection
- res = aSelection->Collapse(selNode,selOffset);
- return res;
- }
- }
+ // track end location of where we are deleting
+ nsAutoTrackDOMPoint tracker(mHTMLEditor->mRangeUpdater, address_of(endNode), &endOffset);
- // else blocks not same type, or not siblings. Delete everything except
- // table elements.
- *aHandled = PR_TRUE;
- nsCOMPtr enumerator;
- nsCOMPtr selPriv(do_QueryInterface(aSelection));
- res = selPriv->GetEnumerator(getter_AddRefs(enumerator));
- if (NS_FAILED(res)) return res;
- if (!enumerator) return NS_ERROR_UNEXPECTED;
+ // block parents the same? use default deletion
+ nsCOMPtr leftParent;
+ nsCOMPtr rightParent;
+ if (IsBlockNode(startNode))
+ leftParent = startNode;
+ else
+ leftParent = mHTMLEditor->GetBlockNodeParent(startNode);
+ if (IsBlockNode(endNode))
+ rightParent = endNode;
+ else
+ rightParent = mHTMLEditor->GetBlockNodeParent(endNode);
+ if (leftParent.get() == rightParent.get()) return NS_OK;
+
+ // deleting across blocks
+ // are the blocks of same type?
+
+ // are the blocks siblings?
+ nsCOMPtr leftBlockParent;
+ nsCOMPtr rightBlockParent;
+ leftParent->GetParentNode(getter_AddRefs(leftBlockParent));
+ rightParent->GetParentNode(getter_AddRefs(rightBlockParent));
- for (enumerator->First(); NS_OK!=enumerator->IsDone(); enumerator->Next())
- {
- nsCOMPtr currentItem;
- res = enumerator->CurrentItem(getter_AddRefs(currentItem));
+ // MOOSE: this could conceivably screw up a table.. fix me.
+ if ( (leftBlockParent.get() == rightBlockParent.get())
+ && (mHTMLEditor->NodesSameType(leftParent, rightParent)) )
+ {
+ if (nsHTMLEditUtils::IsParagraph(leftParent))
+ {
+ // first delete the selection
+ *aHandled = PR_TRUE;
+ res = mHTMLEditor->DeleteSelectionImpl(aAction);
+ if (NS_FAILED(res)) return res;
+ // then join para's, insert break
+ res = mHTMLEditor->JoinNodeDeep(leftParent,rightParent,address_of(selNode),&selOffset);
+ if (NS_FAILED(res)) return res;
+ // fix up selection
+ res = aSelection->Collapse(selNode,selOffset);
+ return res;
+ }
+ if (nsHTMLEditUtils::IsListItem(leftParent)
+ || nsHTMLEditUtils::IsHeader(leftParent))
+ {
+ // first delete the selection
+ *aHandled = PR_TRUE;
+ res = mHTMLEditor->DeleteSelectionImpl(aAction);
+ if (NS_FAILED(res)) return res;
+ // join blocks
+ res = mHTMLEditor->JoinNodeDeep(leftParent,rightParent,address_of(selNode),&selOffset);
+ if (NS_FAILED(res)) return res;
+ // fix up selection
+ res = aSelection->Collapse(selNode,selOffset);
+ return res;
+ }
+ }
+
+ // else blocks not same type, or not siblings. Delete everything except
+ // table elements.
+ *aHandled = PR_TRUE;
+ nsCOMPtr enumerator;
+ nsCOMPtr selPriv(do_QueryInterface(aSelection));
+ res = selPriv->GetEnumerator(getter_AddRefs(enumerator));
if (NS_FAILED(res)) return res;
- if (!currentItem) return NS_ERROR_UNEXPECTED;
+ if (!enumerator) return NS_ERROR_UNEXPECTED;
- // build a list of nodes in the range
- nsCOMPtr range( do_QueryInterface(currentItem) );
- nsCOMPtr arrayOfNodes;
- nsTrivialFunctor functor;
- nsDOMSubtreeIterator iter;
- res = iter.Init(range);
- if (NS_FAILED(res)) return res;
- res = iter.MakeList(functor, address_of(arrayOfNodes));
- if (NS_FAILED(res)) return res;
-
- // now that we have the list, delete non table elements
- PRUint32 listCount;
- PRUint32 j;
- nsCOMPtr somenode;
- nsCOMPtr isupports;
-
- arrayOfNodes->Count(&listCount);
- for (j = 0; j < listCount; j++)
+ for (enumerator->First(); NS_OK!=enumerator->IsDone(); enumerator->Next())
{
- isupports = dont_AddRef(arrayOfNodes->ElementAt(0));
- somenode = do_QueryInterface(isupports);
- res = DeleteNonTableElements(somenode);
- arrayOfNodes->RemoveElementAt(0);
- }
- }
+ nsCOMPtr currentItem;
+ res = enumerator->CurrentItem(getter_AddRefs(currentItem));
+ if (NS_FAILED(res)) return res;
+ if (!currentItem) return NS_ERROR_UNEXPECTED;
+
+ // build a list of nodes in the range
+ nsCOMPtr range( do_QueryInterface(currentItem) );
+ nsCOMPtr arrayOfNodes;
+ nsTrivialFunctor functor;
+ nsDOMSubtreeIterator iter;
+ res = iter.Init(range);
+ if (NS_FAILED(res)) return res;
+ res = iter.MakeList(functor, address_of(arrayOfNodes));
+ if (NS_FAILED(res)) return res;
- // check endopints for possible text deletion.
- // we can assume that if text node is found, we can
- // delete to end or to begining as appropriate,
- // since the case where both sel endpoints in same
- // text node was already handled (we wouldn't be here)
- if ( mHTMLEditor->IsTextNode(startNode) )
- {
- // delete to last character
- nsCOMPtrnodeAsText;
- PRUint32 len;
- nodeAsText = do_QueryInterface(startNode);
- nodeAsText->GetLength(&len);
- if (len > (PRUint32)startOffset)
- {
- res = mHTMLEditor->DeleteText(nodeAsText,startOffset,len-startOffset);
- if (NS_FAILED(res)) return res;
+ // now that we have the list, delete non table elements
+ PRUint32 listCount;
+ PRUint32 j;
+ nsCOMPtr somenode;
+ nsCOMPtr isupports;
+
+ arrayOfNodes->Count(&listCount);
+ for (j = 0; j < listCount; j++)
+ {
+ isupports = dont_AddRef(arrayOfNodes->ElementAt(0));
+ somenode = do_QueryInterface(isupports);
+ res = DeleteNonTableElements(somenode);
+ arrayOfNodes->RemoveElementAt(0);
+ }
}
- }
- if ( mHTMLEditor->IsTextNode(endNode) )
- {
- // delete to first character
- nsCOMPtrnodeAsText;
- nodeAsText = do_QueryInterface(endNode);
- if (endOffset)
+
+ // check endopints for possible text deletion.
+ // we can assume that if text node is found, we can
+ // delete to end or to begining as appropriate,
+ // since the case where both sel endpoints in same
+ // text node was already handled (we wouldn't be here)
+ if ( mHTMLEditor->IsTextNode(startNode) )
{
- res = mHTMLEditor->DeleteText(nodeAsText,0,endOffset);
- if (NS_FAILED(res)) return res;
+ // delete to last character
+ nsCOMPtrnodeAsText;
+ PRUint32 len;
+ nodeAsText = do_QueryInterface(startNode);
+ nodeAsText->GetLength(&len);
+ if (len > (PRUint32)startOffset)
+ {
+ res = mHTMLEditor->DeleteText(nodeAsText,startOffset,len-startOffset);
+ if (NS_FAILED(res)) return res;
+ }
+ }
+ if ( mHTMLEditor->IsTextNode(endNode) )
+ {
+ // delete to first character
+ nsCOMPtrnodeAsText;
+ nodeAsText = do_QueryInterface(endNode);
+ if (endOffset)
+ {
+ res = mHTMLEditor->DeleteText(nodeAsText,0,endOffset);
+ if (NS_FAILED(res)) return res;
+ }
}
}
if (aAction == nsIEditor::eNext)
{
- res = aSelection->Collapse(endNode,0);
+ res = aSelection->Collapse(endNode,endOffset);
}
else
{
@@ -2100,6 +2117,8 @@ nsHTMLEditRules::WillMakeList(nsISelection *aSelection,
if (NS_FAILED(res)) return res;
res = mHTMLEditor->CreateNode(itemType, theList, 0, getter_AddRefs(theListItem));
if (NS_FAILED(res)) return res;
+ // remember our new block for postprocessing
+ mNewBlock = theListItem;
// put selection in new list item
res = aSelection->Collapse(theListItem,0);
selectionResetter.Abort(); // to prevent selection reseter from overriding us.
@@ -2254,6 +2273,8 @@ nsHTMLEditRules::WillMakeList(nsISelection *aSelection,
if (NS_FAILED(res)) return res;
res = mHTMLEditor->CreateNode(*aListType, curParent, offset, getter_AddRefs(curList));
if (NS_FAILED(res)) return res;
+ // remember our new block for postprocessing
+ mNewBlock = curList;
// curList is now the correct thing to put curNode in
prevListItem = 0;
}
@@ -2431,6 +2452,8 @@ nsHTMLEditRules::WillMakeBasicBlock(nsISelection *aSelection,
if (NS_FAILED(res)) return res;
res = mHTMLEditor->CreateNode(*aBlockType, parent, offset, getter_AddRefs(theBlock));
if (NS_FAILED(res)) return res;
+ // remember our new block for postprocessing
+ mNewBlock = theBlock;
// delete anything that was in the list of nodes
nsCOMPtr isupports = dont_AddRef(arrayOfNodes->ElementAt(0));
nsCOMPtr curNode;
@@ -2530,6 +2553,8 @@ nsHTMLEditRules::WillIndent(nsISelection *aSelection, PRBool *aCancel, PRBool *
if (NS_FAILED(res)) return res;
res = mHTMLEditor->CreateNode(quoteType, parent, offset, getter_AddRefs(theBlock));
if (NS_FAILED(res)) return res;
+ // remember our new block for postprocessing
+ mNewBlock = theBlock;
// delete anything that was in the list of nodes
nsCOMPtr isupports = dont_AddRef(arrayOfNodes->ElementAt(0));
nsCOMPtr curNode;
@@ -2587,6 +2612,8 @@ nsHTMLEditRules::WillIndent(nsISelection *aSelection, PRBool *aCancel, PRBool *
res = mHTMLEditor->CreateNode(listTag, curParent, offset, getter_AddRefs(curList));
if (NS_FAILED(res)) return res;
// curList is now the correct thing to put curNode in
+ // remember our new block for postprocessing
+ mNewBlock = curList;
}
// tuck the node into the end of the active list
PRUint32 listLen;
@@ -2607,6 +2634,8 @@ nsHTMLEditRules::WillIndent(nsISelection *aSelection, PRBool *aCancel, PRBool *
if (NS_FAILED(res)) return res;
res = mHTMLEditor->CreateNode(quoteType, curParent, offset, getter_AddRefs(curQuote));
if (NS_FAILED(res)) return res;
+ // remember our new block for postprocessing
+ mNewBlock = curQuote;
/* !!!!!!!!!!!!!!! TURNED OFF PER BUG 33213 !!!!!!!!!!!!!!!!!!!!
// set style to not have unwanted vertical margins
@@ -3134,6 +3163,8 @@ nsHTMLEditRules::WillAlign(nsISelection *aSelection,
}
res = mHTMLEditor->CreateNode(divType, parent, offset, getter_AddRefs(theDiv));
if (NS_FAILED(res)) return res;
+ // remember our new block for postprocessing
+ mNewBlock = theDiv;
// set up the alignment on the div
nsCOMPtr divElem = do_QueryInterface(theDiv);
nsAutoString attr; attr.AssignWithConversion("align");
@@ -3203,6 +3234,8 @@ nsHTMLEditRules::WillAlign(nsISelection *aSelection,
if (NS_FAILED(res)) return res;
res = mHTMLEditor->CreateNode(divType, curParent, offset, getter_AddRefs(curDiv));
if (NS_FAILED(res)) return res;
+ // remember our new block for postprocessing
+ mNewBlock = curDiv;
// set up the alignment on the div
nsCOMPtr divElem = do_QueryInterface(curDiv);
nsAutoString attr; attr.AssignWithConversion("align");
@@ -4918,6 +4951,9 @@ nsHTMLEditRules::MakeBlockquote(nsISupportsArray *arrayOfNodes)
if (NS_FAILED(res)) return res;
res = mHTMLEditor->CreateNode(quoteType, curParent, offset, getter_AddRefs(curBlock));
if (NS_FAILED(res)) return res;
+ // remember our new block for postprocessing
+ mNewBlock = curBlock;
+ // note: doesn't matter if we set mNewBlock multiple times.
}
PRUint32 blockLen;
@@ -5179,6 +5215,9 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsAReadab
if (NS_FAILED(res)) return res;
res = mHTMLEditor->CreateNode(*aBlockTag, curParent, offset, getter_AddRefs(curBlock));
if (NS_FAILED(res)) return res;
+ // remember our new block for postprocessing
+ mNewBlock = curBlock;
+ // note: doesn't matter if we set mNewBlock multiple times.
}
// if curNode is a Break, replace it with a return if we are going to
@@ -5397,6 +5436,111 @@ nsHTMLEditRules::AdjustWhitespace(nsISelection *aSelection)
return nsWSRunObject(mHTMLEditor, selNode, selOffset).AdjustWhitespace();
}
+nsresult
+nsHTMLEditRules::PinSelectionToNewBlock(nsISelection *aSelection)
+{
+ if (!aSelection) return NS_ERROR_NULL_POINTER;
+ PRBool bCollapsed;
+ nsresult res = aSelection->GetIsCollapsed(&bCollapsed);
+ if (NS_FAILED(res)) return res;
+ if (!bCollapsed) return res;
+
+ // get the (collapsed) selection location
+ nsCOMPtr selNode, temp;
+ PRInt32 selOffset;
+ res = mHTMLEditor->GetStartNodeAndOffset(aSelection, address_of(selNode), &selOffset);
+ if (NS_FAILED(res)) return res;
+ temp = selNode;
+
+ // use ranges and mRangeHelper to compare sel point to new block
+ nsCOMPtr range = do_CreateInstance(kRangeCID);
+ res = range->SetStart(selNode, selOffset);
+ if (NS_FAILED(res)) return res;
+ res = range->SetEnd(selNode, selOffset);
+ if (NS_FAILED(res)) return res;
+ nsCOMPtr block (do_QueryInterface(mNewBlock));
+ if (!block) return NS_ERROR_NO_INTERFACE;
+ PRBool nodeBefore, nodeAfter;
+ res = mHTMLEditor->mRangeHelper->CompareNodeToRange(block, range, &nodeBefore, &nodeAfter);
+ if (NS_FAILED(res)) return res;
+
+ if (nodeBefore && nodeAfter)
+ return NS_OK; // selection is inside block
+ else if (nodeBefore)
+ {
+ // selection is after block. put at end of block.
+ nsCOMPtr tmp = mNewBlock;
+ mHTMLEditor->GetLastEditableChild(mNewBlock, address_of(tmp));
+ PRUint32 endPoint;
+ if (mHTMLEditor->IsTextNode(tmp) || mHTMLEditor->IsContainer(tmp))
+ {
+ res = nsEditor::GetLengthOfDOMNode(tmp, endPoint);
+ if (NS_FAILED(res)) return res;
+ }
+ else
+ {
+ nsCOMPtr tmp2;
+ res = nsEditor::GetNodeLocation(tmp, address_of(tmp2), (PRInt32*)&endPoint);
+ if (NS_FAILED(res)) return res;
+ tmp = tmp2;
+ endPoint++; // want to be after this node
+ }
+ return aSelection->Collapse(tmp, (PRInt32)endPoint);
+ }
+ else
+ {
+ // selection is before block. put at start of block.
+ nsCOMPtr tmp = mNewBlock;
+ mHTMLEditor->GetFirstEditableChild(mNewBlock, address_of(tmp));
+ PRInt32 offset;
+ if (!(mHTMLEditor->IsTextNode(tmp) || mHTMLEditor->IsContainer(tmp)))
+ {
+ nsCOMPtr tmp2;
+ res = nsEditor::GetNodeLocation(tmp, address_of(tmp2), &offset);
+ if (NS_FAILED(res)) return res;
+ tmp = tmp2;
+ }
+ return aSelection->Collapse(tmp, 0);
+ }
+}
+
+nsresult
+nsHTMLEditRules::CheckInterlinePosition(nsISelection *aSelection)
+{
+ if (!aSelection) return NS_ERROR_NULL_POINTER;
+ nsCOMPtr selection(aSelection);
+ nsCOMPtr selPriv(do_QueryInterface(selection));
+
+ // if the selection isn't collapsed, do nothing.
+ PRBool bCollapsed;
+ nsresult res = aSelection->GetIsCollapsed(&bCollapsed);
+ if (NS_FAILED(res)) return res;
+ if (!bCollapsed) return res;
+
+ // get the (collapsed) selection location
+ nsCOMPtr selNode, node;
+ PRInt32 selOffset;
+ res = mHTMLEditor->GetStartNodeAndOffset(aSelection, address_of(selNode), &selOffset);
+ if (NS_FAILED(res)) return res;
+
+ // are we after a block? If so try set caret to following content
+ mHTMLEditor->GetPriorHTMLSibling(selNode, selOffset, address_of(node));
+ if (node && IsBlockNode(node))
+ {
+ selPriv->SetInterlinePosition(PR_TRUE);
+ return NS_OK;
+ }
+
+ // are we before a block? If so try set caret to prior content
+ mHTMLEditor->GetNextHTMLSibling(selNode, selOffset, address_of(node));
+ if (node && IsBlockNode(node))
+ {
+ selPriv->SetInterlinePosition(PR_FALSE);
+ return NS_OK;
+ }
+ return NS_OK;
+}
+
nsresult
nsHTMLEditRules::AdjustSelection(nsISelection *aSelection, nsIEditor::EDirection aAction)
{
diff --git a/mozilla/editor/libeditor/html/nsHTMLEditRules.h b/mozilla/editor/libeditor/html/nsHTMLEditRules.h
index 6738407d515..e9b9c791926 100644
--- a/mozilla/editor/libeditor/html/nsHTMLEditRules.h
+++ b/mozilla/editor/libeditor/html/nsHTMLEditRules.h
@@ -179,6 +179,8 @@ protected:
nsresult RemoveListStructure(nsIDOMNode *aList);
nsresult AdjustSpecialBreaks(PRBool aSafeToAskFrames = PR_FALSE);
nsresult AdjustWhitespace(nsISelection *aSelection);
+ nsresult PinSelectionToNewBlock(nsISelection *aSelection);
+ nsresult CheckInterlinePosition(nsISelection *aSelection);
nsresult AdjustSelection(nsISelection *aSelection, nsIEditor::EDirection aAction);
nsresult FindNearSelectableNode(nsIDOMNode *aSelNode,
PRInt32 aSelOffset,
@@ -202,6 +204,7 @@ protected:
PRBool mReturnInEmptyLIKillsList;
nsCOMPtr mUtilRange;
PRUint32 mJoinOffset; // need to remember an int across willJoin/didJoin...
+ nsCOMPtr mNewBlock;
};