mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
implementing font increase/decrease size for html editor (bug 18774) r=floppy moose
This commit is contained in:
parent
f51f453392
commit
c9505c0fa5
@ -49,7 +49,7 @@ class nsEditRules
|
||||
public:
|
||||
NS_IMETHOD Init(nsHTMLEditor *aEditor, PRUint32 aFlags)=0;
|
||||
NS_IMETHOD BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection)=0;
|
||||
NS_IMETHOD AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)=0;
|
||||
NS_IMETHOD AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection, PRBool aSetSelection)=0;
|
||||
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel, PRBool *aHandled)=0;
|
||||
NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult)=0;
|
||||
NS_IMETHOD GetFlags(PRUint32 *aFlags)=0;
|
||||
|
@ -1787,7 +1787,7 @@ nsEditor::StartOperation(PRInt32 opID, nsIEditor::EDirection aDirection)
|
||||
/** All editor operations which alter the doc should be followed
|
||||
* with a call to EndOperation, naming the action and direction */
|
||||
NS_IMETHODIMP
|
||||
nsEditor::EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection)
|
||||
nsEditor::EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection, PRBool aSetSelection)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
@ -3304,22 +3304,41 @@ nsEditor::NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEditor::CanContainTag(nsIDOMNode* aParent, const nsString &aTag)
|
||||
nsEditor::CanContainTag(nsIDOMNode* aParent, const nsString &aChildTag)
|
||||
{
|
||||
// if we don't have a dtd then assume we can insert whatever want
|
||||
if (!mDTD) return PR_TRUE;
|
||||
|
||||
PRInt32 childTagEnum, parentTagEnum;
|
||||
nsAutoString parentStringTag;
|
||||
nsAutoString non_const_aTag(aTag);
|
||||
nsresult res = mDTD->StringTagToIntTag(non_const_aTag,&childTagEnum);
|
||||
if (NS_FAILED(res)) return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> parentElement = do_QueryInterface(aParent);
|
||||
if (!parentElement) return PR_FALSE;
|
||||
|
||||
parentElement->GetTagName(parentStringTag);
|
||||
res = mDTD->StringTagToIntTag(parentStringTag,&parentTagEnum);
|
||||
return TagCanContainTag(parentStringTag, aChildTag);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEditor::TagCanContain(const nsString &aParentTag, nsIDOMNode* aChild)
|
||||
{
|
||||
nsAutoString childStringTag;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> childElement = do_QueryInterface(aChild);
|
||||
if (!childElement) return PR_FALSE;
|
||||
|
||||
childElement->GetTagName(childStringTag);
|
||||
return TagCanContainTag(aParentTag, childStringTag);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEditor::TagCanContainTag(const nsString &aParentTag, const nsString &aChildTag)
|
||||
{
|
||||
// if we don't have a dtd then assume we can insert whatever want
|
||||
if (!mDTD) return PR_TRUE;
|
||||
|
||||
PRInt32 childTagEnum, parentTagEnum;
|
||||
nsAutoString non_const_childTag(aChildTag);
|
||||
nsAutoString non_const_parentTag(aParentTag);
|
||||
nsresult res = mDTD->StringTagToIntTag(non_const_childTag,&childTagEnum);
|
||||
if (NS_FAILED(res)) return PR_FALSE;
|
||||
res = mDTD->StringTagToIntTag(non_const_parentTag,&parentTagEnum);
|
||||
if (NS_FAILED(res)) return PR_FALSE;
|
||||
|
||||
return mDTD->CanContain(parentTagEnum, childTagEnum);
|
||||
|
@ -422,7 +422,7 @@ public:
|
||||
|
||||
/** All editor operations which alter the doc should be followed
|
||||
* with a call to EndOperation, naming the action and direction */
|
||||
NS_IMETHOD EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection);
|
||||
NS_IMETHOD EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection, PRBool aSetSelection);
|
||||
|
||||
/** return the string that represents text nodes in the content tree */
|
||||
static nsresult GetTextNodeTag(nsString& aOutString);
|
||||
@ -608,6 +608,8 @@ public:
|
||||
|
||||
/** returns PR_TRUE if aParent can contain a child of type aTag */
|
||||
PRBool CanContainTag(nsIDOMNode* aParent, const nsString &aTag);
|
||||
PRBool TagCanContain(const nsString &aParentTag, nsIDOMNode* aChild);
|
||||
PRBool TagCanContainTag(const nsString &aParentTag, const nsString &aChildTag);
|
||||
|
||||
/** returns PR_TRUE if aNode is a container */
|
||||
PRBool IsContainer(nsIDOMNode *aNode);
|
||||
|
@ -93,15 +93,16 @@ class nsAutoRules
|
||||
{
|
||||
public:
|
||||
|
||||
nsAutoRules(nsEditor *ed, PRInt32 action, nsIEditor::EDirection aDirection) :
|
||||
mEd(ed), mAction(action), mDirection(aDirection)
|
||||
nsAutoRules(nsEditor *ed, PRInt32 action, nsIEditor::EDirection aDirection, PRBool setSelection=PR_FALSE) :
|
||||
mEd(ed), mAction(action), mDirection(aDirection), mSetSelection(setSelection)
|
||||
{if (mEd) mEd->StartOperation(mAction, mDirection);}
|
||||
~nsAutoRules() {if (mEd) mEd->EndOperation(mAction, mDirection);}
|
||||
~nsAutoRules() {if (mEd) mEd->EndOperation(mAction, mDirection, mSetSelection);}
|
||||
|
||||
protected:
|
||||
nsEditor *mEd;
|
||||
PRInt32 mAction;
|
||||
nsIEditor::EDirection mDirection;
|
||||
PRBool mSetSelection;
|
||||
};
|
||||
|
||||
|
||||
|
@ -148,7 +148,7 @@ nsHTMLEditRules::BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
||||
nsHTMLEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection, PRBool aSetSelection)
|
||||
{
|
||||
if (mLockRulesSniffing) return NS_OK;
|
||||
|
||||
@ -172,8 +172,16 @@ nsHTMLEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
||||
nsAutoTxnsConserveSelection dontSpazMySelection(mEditor);
|
||||
|
||||
// expand the "changed doc range" as needed
|
||||
// MOOSE: I don't do this if the aSetSelection param is true. This is because
|
||||
// if aSetSelection is true, it means we are to set the selection to the changed
|
||||
// document region when we are done. So I need to preserve mDocChangeRange as is.
|
||||
// I should probably set up a parellel range for this purpose.
|
||||
|
||||
if (!aSetSelection)
|
||||
{
|
||||
res = PromoteRange(mDocChangeRange, action);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
// add in any needed <br>s, and remove any unneeded ones.
|
||||
res = AdjustSpecialBreaks();
|
||||
@ -208,6 +216,12 @@ nsHTMLEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
||||
nsCOMPtr<nsIPresShell> pres;
|
||||
mEditor->GetPresShell(getter_AddRefs(pres));
|
||||
if (pres) pres->SetCaretEnabled(PR_TRUE);
|
||||
|
||||
if (aSetSelection)
|
||||
{
|
||||
selection->ClearSelection();
|
||||
selection->AddRange(mDocChangeRange);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
@ -1100,7 +1114,7 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection,
|
||||
{
|
||||
// make a new ordered list, insert it where the current unordered list is,
|
||||
// and move all the children to the new list, and remove the old list
|
||||
res = ReplaceContainer(curNode,&newBlock,blockType);
|
||||
res = mEditor->ReplaceContainer(curNode,&newBlock,blockType);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curList = newBlock;
|
||||
continue;
|
||||
@ -1118,7 +1132,7 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection,
|
||||
{
|
||||
// make a new unordered list, insert it where the current ordered list is,
|
||||
// and move all the children to the new list, and remove the old list
|
||||
ReplaceContainer(curNode,&newBlock,blockType);
|
||||
mEditor->ReplaceContainer(curNode,&newBlock,blockType);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curList = newBlock;
|
||||
continue;
|
||||
@ -1179,11 +1193,11 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection,
|
||||
// don't wrap li around a paragraph. instead replace paragraph with li
|
||||
if (nsHTMLEditUtils::IsParagraph(curNode))
|
||||
{
|
||||
res = ReplaceContainer(curNode, &listItem, "li");
|
||||
res = mEditor->ReplaceContainer(curNode, &listItem, "li");
|
||||
}
|
||||
else
|
||||
{
|
||||
res = InsertContainerAbove(curNode, &listItem, "li");
|
||||
res = mEditor->InsertContainerAbove(curNode, &listItem, "li");
|
||||
}
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nsEditor::IsInlineNode(curNode))
|
||||
@ -1503,7 +1517,7 @@ nsHTMLEditRules::WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBoo
|
||||
{
|
||||
if (nsHTMLEditUtils::IsList(curNode)) // just unwrap this sublist
|
||||
{
|
||||
res = RemoveContainer(curNode);
|
||||
res = mEditor->RemoveContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else // we are moving a list item, but not whole list
|
||||
@ -1547,7 +1561,7 @@ nsHTMLEditRules::WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBoo
|
||||
{
|
||||
if (nsHTMLEditUtils::IsBlockquote(n))
|
||||
{
|
||||
RemoveContainer(n);
|
||||
mEditor->RemoveContainer(n);
|
||||
break;
|
||||
}
|
||||
n->GetParentNode(getter_AddRefs(tmp));
|
||||
@ -2347,142 +2361,6 @@ nsHTMLEditRules::MakeTransitionList(nsISupportsArray *inArrayOfNodes,
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ReplaceContainer: replace inNode with a new node (outNode) which is contructed
|
||||
// to be of type aNodeType. Put inNodes children into outNode.
|
||||
// Callers responsibility to make sure inNode's children can
|
||||
// go in outNode.
|
||||
nsresult
|
||||
nsHTMLEditRules::ReplaceContainer(nsIDOMNode *inNode,
|
||||
nsCOMPtr<nsIDOMNode> *outNode,
|
||||
const nsString &aNodeType)
|
||||
{
|
||||
if (!inNode || !outNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset;
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->CreateNode(aNodeType, parent, offset, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
PRBool bHasMoreChildren;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
offset = 0;
|
||||
while (bHasMoreChildren)
|
||||
{
|
||||
inNode->GetLastChild(getter_AddRefs(child));
|
||||
res = mEditor->DeleteNode(child);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->InsertNode(child, *outNode, 0);
|
||||
if (NS_FAILED(res)) return res;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
}
|
||||
res = mEditor->DeleteNode(inNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// RemoveContainer: remove inNode, reparenting it's children into their
|
||||
// the parent of inNode
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::RemoveContainer(nsIDOMNode *inNode, PRBool aAddBRIfNeeded)
|
||||
{
|
||||
if (!inNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (nsHTMLEditUtils::IsBody(inNode))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset;
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// add BR's before and/or after the inNode
|
||||
// if aAddBRIfNeeded is set and if the content
|
||||
// before/after the node is inline.
|
||||
// Only do this if inNode is a block node.
|
||||
if (aAddBRIfNeeded && mEditor->IsBlockNode(inNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> nearNode, brNode;
|
||||
res = GetPriorHTMLSibling(inNode, &nearNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nearNode && mEditor->IsInlineNode(nearNode))
|
||||
{
|
||||
res = mEditor->CreateBR(parent, offset, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// refresh location info
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
res = GetNextHTMLSibling(inNode, &nearNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nearNode && mEditor->IsInlineNode(nearNode))
|
||||
{
|
||||
res = mEditor->CreateBR(parent, offset+1, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// refresh location info
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
|
||||
// loop through the child nodes of inNode and promote them
|
||||
// into inNode's parent.
|
||||
PRBool bHasMoreChildren;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
while (bHasMoreChildren)
|
||||
{
|
||||
inNode->GetLastChild(getter_AddRefs(child));
|
||||
res = mEditor->DeleteNode(child);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->InsertNode(child, parent, offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
}
|
||||
res = mEditor->DeleteNode(inNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// InsertContainerAbove: insert a new parent for inNode, returned in outNode,
|
||||
// which is contructed to be of type aNodeType. outNode becomes
|
||||
// a child of inNode's earlier parent.
|
||||
// Callers responsibility to make sure inNode's can be child
|
||||
// of outNode, and outNode can be child of old parent.
|
||||
nsresult
|
||||
nsHTMLEditRules::InsertContainerAbove(nsIDOMNode *inNode,
|
||||
nsCOMPtr<nsIDOMNode> *outNode,
|
||||
const nsString &aNodeType)
|
||||
{
|
||||
if (!inNode || !outNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset;
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// make new parent, outNode
|
||||
res = mEditor->CreateNode(aNodeType, parent, offset, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// put inNode in new parent, outNode
|
||||
res = mEditor->DeleteNode(inNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->InsertNode(inNode, *outNode, 0);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/********************************************************
|
||||
* main implementation methods
|
||||
@ -2558,7 +2436,7 @@ nsHTMLEditRules::ReturnInHeader(nsIDOMSelection *aSelection,
|
||||
}
|
||||
// else unwrap it
|
||||
nsCOMPtr<nsIDOMNode> newBlock;
|
||||
res = RemoveContainer(aHeader);
|
||||
res = mEditor->RemoveContainer(aHeader);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -2958,11 +2836,11 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString
|
||||
// nsCOMPtr<nsIDOMNode> brNode;
|
||||
// res = mEditor->CreateBR(curParent, offset+1, &brNode);
|
||||
// if (NS_FAILED(res)) return res;
|
||||
res = RemoveContainer(curNode, PR_TRUE);
|
||||
res = mEditor->RemoveContainer(curNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ReplaceContainer(curNode, &newBlock, *aBlockTag);
|
||||
res = mEditor->ReplaceContainer(curNode, &newBlock, *aBlockTag);
|
||||
}
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
@ -3743,7 +3621,7 @@ nsHTMLEditRules::PopListItem(nsIDOMNode *aListItem, PRBool *aOutOfList)
|
||||
nsCOMPtr<nsIDOMNode> lastChild;
|
||||
res = GetLastEditableChild(curNode, &lastChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = RemoveContainer(curNode);
|
||||
res = mEditor->RemoveContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (mEditor->IsInlineNode(lastChild))
|
||||
{
|
||||
@ -4003,15 +3881,9 @@ nsHTMLEditListener::DidSplitNode(nsIDOMNode *aExistingRightNode,
|
||||
nsresult aResult)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
nsresult res = MakeRangeFromNode(aNewLeftNode, &range);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (range)
|
||||
{
|
||||
// now extend range to include right node
|
||||
res = range->SetEndAfter(aExistingRightNode);
|
||||
nsresult res = MakeCollapsedRange(aExistingRightNode, 0, &range);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mRules->UpdateDocChangeRange(range);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -4019,7 +3891,9 @@ nsHTMLEditListener::DidSplitNode(nsIDOMNode *aExistingRightNode,
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditListener::WillJoinNodes(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, nsIDOMNode *aParent)
|
||||
{
|
||||
return NS_OK;
|
||||
// remember split point
|
||||
nsresult res = nsEditor::GetLengthOfDOMNode(aLeftNode, mJoinOffset);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@ -4029,14 +3903,11 @@ nsHTMLEditListener::DidJoinNodes(nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aParent,
|
||||
nsresult aResult)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
// assumption that Join keeps the righthand node
|
||||
nsresult res = MakeRangeFromNode(aRightNode, &range);
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
nsresult res = MakeCollapsedRange(aRightNode, mJoinOffset, &range);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (range)
|
||||
{
|
||||
res = mRules->UpdateDocChangeRange(range);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -4143,6 +4014,28 @@ nsHTMLEditListener::MakeRangeFromNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMRange>
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditListener::MakeCollapsedRange(nsIDOMNode *inNode, PRInt32 inOffset, nsCOMPtr<nsIDOMRange> *outRange)
|
||||
{
|
||||
if (!inNode || !outRange) return NS_ERROR_NULL_POINTER;
|
||||
*outRange = nsnull;
|
||||
|
||||
// first check that inNode is still a descendant of the body
|
||||
if (!IsDescendantOfBody(inNode)) return NS_OK;
|
||||
|
||||
// construct a range to represent start and end of inNode
|
||||
nsresult res = nsComponentManager::CreateInstance(kRangeCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIDOMRange),
|
||||
getter_AddRefs(*outRange));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = (*outRange)->SetStart(inNode, inOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = (*outRange)->SetEnd(inNode, inOffset);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditListener::MakeRangeFromTextOffsets(nsIDOMCharacterData *inNode,
|
||||
PRInt32 inStart,
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
|
||||
// nsEditRules methods
|
||||
NS_IMETHOD BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection);
|
||||
NS_IMETHOD AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection);
|
||||
NS_IMETHOD AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection, PRBool aSetSelection);
|
||||
NS_IMETHOD Init(nsHTMLEditor *aEditor, PRUint32 aFlags);
|
||||
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel, PRBool *aHandled);
|
||||
NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult);
|
||||
@ -111,10 +111,6 @@ protected:
|
||||
nsresult ShouldMakeEmptyBlock(nsIDOMSelection *aSelection, const nsString *blockTag, PRBool *outMakeEmpty);
|
||||
nsresult ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString *aBlockTag);
|
||||
|
||||
nsresult ReplaceContainer(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, const nsString &aNodeType);
|
||||
nsresult RemoveContainer(nsIDOMNode *inNode, PRBool aAddBRIfNeeded=PR_FALSE);
|
||||
nsresult InsertContainerAbove(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, const nsString &aNodeType);
|
||||
|
||||
nsresult JoinNodesSmart( nsIDOMNode *aNodeLeft,
|
||||
nsIDOMNode *aNodeRight,
|
||||
nsCOMPtr<nsIDOMNode> *aOutMergeParent,
|
||||
@ -189,12 +185,14 @@ protected:
|
||||
PRInt32 inStart,
|
||||
PRInt32 inEnd,
|
||||
nsCOMPtr<nsIDOMRange> *outRange);
|
||||
nsresult MakeCollapsedRange(nsIDOMNode *inNode, PRInt32 inOffset, nsCOMPtr<nsIDOMRange> *outRange);
|
||||
PRBool IsDescendantOfBody(nsIDOMNode *inNode) ;
|
||||
|
||||
// data members
|
||||
nsHTMLEditor *mEditor;
|
||||
nsHTMLEditRules *mRules;
|
||||
nsCOMPtr<nsIDOMNode> mBody;
|
||||
PRUint32 mJoinOffset; // need to remember an int across willJoin/didJoin...
|
||||
};
|
||||
|
||||
#endif //nsHTMLEditRules_h__
|
||||
|
@ -68,6 +68,42 @@ nsHTMLEditUtils::IsBreak(nsIDOMNode *node)
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBreak: true if node an html break node
|
||||
//
|
||||
PRBool
|
||||
nsHTMLEditUtils::IsBig(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsHTMLEditUtils::IsBig");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "big")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBreak: true if node an html break node
|
||||
//
|
||||
PRBool
|
||||
nsHTMLEditUtils::IsSmall(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsHTMLEditUtils::IsSmall");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "small")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsMozBR: true if node an html br node with type = _moz
|
||||
//
|
||||
|
@ -34,6 +34,8 @@ public:
|
||||
// from nsTextEditRules:
|
||||
static PRBool IsBody(nsIDOMNode *aNode);
|
||||
static PRBool IsBreak(nsIDOMNode *aNode);
|
||||
static PRBool IsBig(nsIDOMNode *aNode);
|
||||
static PRBool IsSmall(nsIDOMNode *aNode);
|
||||
static PRBool IsMozBR(nsIDOMNode *aNode);
|
||||
static PRBool HasMozAttr(nsIDOMNode *aNode);
|
||||
static PRBool InBody(nsIDOMNode *aNode);
|
||||
|
@ -102,6 +102,7 @@ static NS_DEFINE_CID(kCNavDTDCID, NS_CNAVDTD_CID);
|
||||
|
||||
static NS_DEFINE_CID(kHTMLEditorCID, NS_HTMLEDITOR_CID);
|
||||
static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID);
|
||||
static NS_DEFINE_IID(kSubtreeIteratorCID, NS_SUBTREEITERATOR_CID);
|
||||
static NS_DEFINE_CID(kCRangeCID, NS_RANGE_CID);
|
||||
static NS_DEFINE_IID(kFileWidgetCID, NS_FILEWIDGET_CID);
|
||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||
@ -1341,14 +1342,12 @@ NS_IMETHODIMP nsHTMLEditor::RemoveInlineProperty(nsIAtom *aProperty, const nsStr
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::IncreaseFontSize()
|
||||
{
|
||||
//TODO: Write this!
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return RelativeFontChange(1);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::DecreaseFontSize()
|
||||
{
|
||||
//TODO: Write this!
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return RelativeFontChange(-1);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::GetTypingState(nsIAtom *aProperty, PRBool &aPropIsSet, PRBool &aSetting)
|
||||
@ -4512,11 +4511,11 @@ nsHTMLEditor::StartOperation(PRInt32 opID, nsIEditor::EDirection aDirection)
|
||||
/** All editor operations which alter the doc should be followed
|
||||
* with a call to EndOperation, naming the action and direction */
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection)
|
||||
nsHTMLEditor::EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection, PRBool aSetSelection)
|
||||
{
|
||||
if (! ((opID==kOpInsertText) || (opID==kOpInsertIMEText)) )
|
||||
ClearInlineStylesCache();
|
||||
if (mRules) return mRules->AfterEdit(opID, aDirection);
|
||||
if (mRules) return mRules->AfterEdit(opID, aDirection, aSetSelection);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -7213,7 +7212,7 @@ nsHTMLEditor::CollapseAdjacentTextNodes(nsIDOMSelection *aInSelection)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
nsCOMPtr<nsIContentIterator> iter;
|
||||
result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull,
|
||||
result = nsComponentManager::CreateInstance(kSubtreeIteratorCID, nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(iter));
|
||||
if (NS_FAILED(result)) return result;
|
||||
@ -7376,3 +7375,368 @@ nsHTMLEditor::GetNextElementByTagName(nsIDOMElement *aCurrentElement,
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::RelativeFontChange( PRInt32 aSizeChange)
|
||||
{
|
||||
// Can only change font size by + or - 1
|
||||
if ( !( (aSizeChange==1) || (aSizeChange==-1) ) )
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
ForceCompositionEnd();
|
||||
|
||||
// wrap with txn batching, rules sniffing, and selection preservation code
|
||||
nsAutoEditBatch batchIt(this);
|
||||
nsAutoRules beginRulesSniffing(this, kOpSetTextProperty, nsIEditor::eNext, PR_TRUE);
|
||||
|
||||
// Get the selection
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!selection) return NS_ERROR_FAILURE;
|
||||
|
||||
// Is the selection collapsed?
|
||||
PRBool bCollapsed;
|
||||
res = selection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's collapsed dont do anything.
|
||||
// MOOSE: We should probably have typing state for this like
|
||||
// we do for other things.
|
||||
if (bCollapsed)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// get selection range enumerator
|
||||
nsCOMPtr<nsIEnumerator> enumerator;
|
||||
res = selection->GetEnumerator(getter_AddRefs(enumerator));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!enumerator) return NS_ERROR_FAILURE;
|
||||
|
||||
// loop thru the ranges in the selection
|
||||
enumerator->First();
|
||||
nsCOMPtr<nsISupports> currentItem;
|
||||
while ((NS_ENUMERATOR_FALSE == enumerator->IsDone()))
|
||||
{
|
||||
res = enumerator->CurrentItem(getter_AddRefs(currentItem));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!currentItem) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
|
||||
// check for easy case: both range endpoints in same text node
|
||||
nsCOMPtr<nsIDOMNode> startNode, endNode;
|
||||
res = range->GetStartParent(getter_AddRefs(startNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = range->GetEndParent(getter_AddRefs(endNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if ((startNode == endNode) && IsTextNode(startNode))
|
||||
{
|
||||
PRInt32 startOffset, endOffset;
|
||||
range->GetStartOffset(&startOffset);
|
||||
range->GetEndOffset(&endOffset);
|
||||
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(startNode);
|
||||
res = RelativeFontChangeOnTextNode(aSizeChange, nodeAsText, startOffset, endOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// not the easy case. range not contained in single text node.
|
||||
// there are up to three phases here. There are all the nodes
|
||||
// reported by the subtree iterator to be processed. And there
|
||||
// are potentially a starting textnode and an ending textnode
|
||||
// which are only partially contained by the range.
|
||||
|
||||
// lets handle the nodes reported by the iterator. These nodes
|
||||
// are entirely contained in the selection range. We build up
|
||||
// a list of them (since doing operations on the document during
|
||||
// iteration would perturb the iterator).
|
||||
|
||||
nsCOMPtr<nsIContentIterator> iter;
|
||||
res = nsComponentManager::CreateInstance(kSubtreeIteratorCID, nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(iter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!iter) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISupportsArray> arrayOfNodes;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
|
||||
// make a array
|
||||
res = NS_NewISupportsArray(getter_AddRefs(arrayOfNodes));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// iterate range and build up array
|
||||
iter->Init(range);
|
||||
while (NS_ENUMERATOR_FALSE == iter->IsDone())
|
||||
{
|
||||
res = iter->CurrentNode(getter_AddRefs(content));
|
||||
if (NS_FAILED(res)) return res;
|
||||
node = do_QueryInterface(content);
|
||||
if (!node) return NS_ERROR_FAILURE;
|
||||
isupports = do_QueryInterface(node);
|
||||
arrayOfNodes->AppendElement(isupports);
|
||||
res = iter->Next();
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
// now that we have the list, do the font size change on each node
|
||||
PRUint32 listCount;
|
||||
PRInt32 j;
|
||||
arrayOfNodes->Count(&listCount);
|
||||
for (j = 0; j < listCount; j++)
|
||||
{
|
||||
isupports = (dont_AddRef)(arrayOfNodes->ElementAt(0));
|
||||
node = do_QueryInterface(isupports);
|
||||
res = RelativeFontChangeOnNode(aSizeChange, node);
|
||||
if (NS_FAILED(res)) return res;
|
||||
arrayOfNodes->RemoveElementAt(0);
|
||||
}
|
||||
|
||||
// now check the start and end parents of the range to see if they need to
|
||||
// be seperately handled (they do if they are text nodes, due to how the
|
||||
// subtree iterator works - it will not have reported them).
|
||||
if (IsTextNode(startNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(startNode);
|
||||
PRInt32 startOffset;
|
||||
PRUint32 textLen;
|
||||
range->GetStartOffset(&startOffset);
|
||||
nodeAsText->GetLength(&textLen);
|
||||
res = RelativeFontChangeOnTextNode(aSizeChange, nodeAsText, startOffset, textLen);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
if (IsTextNode(endNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(endNode);
|
||||
PRInt32 endOffset;
|
||||
range->GetEndOffset(&endOffset);
|
||||
res = RelativeFontChangeOnTextNode(aSizeChange, nodeAsText, 0, endOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
enumerator->Next();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::RelativeFontChangeOnTextNode( PRInt32 aSizeChange,
|
||||
nsIDOMCharacterData *aTextNode,
|
||||
PRInt32 aStartOffset,
|
||||
PRInt32 aEndOffset)
|
||||
{
|
||||
// Can only change font size by + or - 1
|
||||
if ( !( (aSizeChange==1) || (aSizeChange==-1) ) )
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
if (!aTextNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// dont need to do anything if no characters actually selected
|
||||
if (aStartOffset == aEndOffset) return NS_OK;
|
||||
|
||||
nsresult res = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> tmp, node = do_QueryInterface(aTextNode);
|
||||
|
||||
// do we need to split the text node?
|
||||
PRUint32 textLen;
|
||||
aTextNode->GetLength(&textLen);
|
||||
|
||||
if ( aEndOffset != textLen )
|
||||
{
|
||||
// we need to split off back of text node
|
||||
res = SplitNode(node, aEndOffset, getter_AddRefs(tmp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
node = tmp; // remember left node
|
||||
}
|
||||
if ( aStartOffset )
|
||||
{
|
||||
// we need to split off front of text node
|
||||
res = SplitNode(node, aStartOffset, getter_AddRefs(tmp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
// reparent the node inside font node with appropriate relative size
|
||||
nsAutoString tag;
|
||||
if (aSizeChange == 1) tag = "big";
|
||||
else tag = "small";
|
||||
res = InsertContainerAbove(node, &tmp, tag);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::RelativeFontChangeOnNode( PRInt32 aSizeChange,
|
||||
nsIDOMNode *aNode)
|
||||
{
|
||||
// Can only change font size by + or - 1
|
||||
if ( !( (aSizeChange==1) || (aSizeChange==-1) ) )
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
if (!aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult res = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
nsAutoString tag;
|
||||
if (aSizeChange == 1) tag = "big";
|
||||
else tag = "small";
|
||||
|
||||
// is this node a text node?
|
||||
if (IsTextNode(aNode))
|
||||
{
|
||||
res = InsertContainerAbove(aNode, &tmp, tag);
|
||||
return res;
|
||||
}
|
||||
// is it the opposite of what we want?
|
||||
if ( ((aSizeChange == 1) && nsHTMLEditUtils::IsSmall(aNode)) ||
|
||||
((aSizeChange == -1) && nsHTMLEditUtils::IsBig(aNode)) )
|
||||
{
|
||||
// in that case, just remove this node and pull up the children
|
||||
res = RemoveContainer(aNode);
|
||||
return res;
|
||||
}
|
||||
// can it be put inside a "big" or "small"?
|
||||
if (TagCanContain(tag, aNode))
|
||||
{
|
||||
// ok, chuck it in.
|
||||
res = InsertContainerAbove(aNode, &tmp, tag);
|
||||
return res;
|
||||
}
|
||||
// none of the above? then cycle through the children.
|
||||
// MOOSE: we should group the children together if possible
|
||||
// into a single "big" or "small". For the moment they are
|
||||
// each getting their own.
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
res = aNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (childNodes)
|
||||
{
|
||||
PRInt32 j;
|
||||
PRUint32 childCount;
|
||||
childNodes->GetLength(&childCount);
|
||||
for (j=0 ; j<childCount; j++)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
res = childNodes->Item(j, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(res)) && (childNode))
|
||||
{
|
||||
res = RelativeFontChangeOnNode(aSizeChange, childNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ReplaceContainer: replace inNode with a new node (outNode) which is contructed
|
||||
// to be of type aNodeType. Put inNodes children into outNode.
|
||||
// Callers responsibility to make sure inNode's children can
|
||||
// go in outNode.
|
||||
nsresult
|
||||
nsHTMLEditor::ReplaceContainer(nsIDOMNode *inNode,
|
||||
nsCOMPtr<nsIDOMNode> *outNode,
|
||||
const nsString &aNodeType)
|
||||
{
|
||||
if (!inNode || !outNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset;
|
||||
res = GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = CreateNode(aNodeType, parent, offset, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
PRBool bHasMoreChildren;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
offset = 0;
|
||||
while (bHasMoreChildren)
|
||||
{
|
||||
inNode->GetLastChild(getter_AddRefs(child));
|
||||
res = DeleteNode(child);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = InsertNode(child, *outNode, 0);
|
||||
if (NS_FAILED(res)) return res;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
}
|
||||
res = DeleteNode(inNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// RemoveContainer: remove inNode, reparenting it's children into their
|
||||
// the parent of inNode
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditor::RemoveContainer(nsIDOMNode *inNode)
|
||||
{
|
||||
if (!inNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (nsHTMLEditUtils::IsBody(inNode))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset;
|
||||
res = GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// loop through the child nodes of inNode and promote them
|
||||
// into inNode's parent.
|
||||
PRBool bHasMoreChildren;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
while (bHasMoreChildren)
|
||||
{
|
||||
inNode->GetLastChild(getter_AddRefs(child));
|
||||
res = DeleteNode(child);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = InsertNode(child, parent, offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
}
|
||||
res = DeleteNode(inNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// InsertContainerAbove: insert a new parent for inNode, returned in outNode,
|
||||
// which is contructed to be of type aNodeType. outNode becomes
|
||||
// a child of inNode's earlier parent.
|
||||
// Callers responsibility to make sure inNode's can be child
|
||||
// of outNode, and outNode can be child of old parent.
|
||||
nsresult
|
||||
nsHTMLEditor::InsertContainerAbove(nsIDOMNode *inNode,
|
||||
nsCOMPtr<nsIDOMNode> *outNode,
|
||||
const nsString &aNodeType)
|
||||
{
|
||||
if (!inNode || !outNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset;
|
||||
res = GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// make new parent, outNode
|
||||
res = CreateNode(aNodeType, parent, offset, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// put inNode in new parent, outNode
|
||||
res = DeleteNode(inNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = InsertNode(inNode, *outNode, 0);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -260,7 +260,7 @@ public:
|
||||
|
||||
/** All editor operations which alter the doc should be followed
|
||||
* with a call to EndOperation, naming the action and direction */
|
||||
NS_IMETHOD EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection);
|
||||
NS_IMETHOD EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection, PRBool aSetSelection);
|
||||
|
||||
/** returns PR_TRUE if aParent can contain a child of type aTag */
|
||||
PRBool CanContainTag(nsIDOMNode* aParent, const nsString &aTag);
|
||||
@ -546,6 +546,23 @@ protected:
|
||||
/* small utility routine to test the eEditorReadonly bit */
|
||||
PRBool IsModifiable();
|
||||
|
||||
/* increase/decrease the font size of selection */
|
||||
nsresult RelativeFontChange( PRInt32 aSizeChange);
|
||||
|
||||
/* helper routines for font size changing */
|
||||
nsresult RelativeFontChangeOnTextNode( PRInt32 aSizeChange,
|
||||
nsIDOMCharacterData *aTextNode,
|
||||
PRInt32 aStartOffset,
|
||||
PRInt32 aEndOffset);
|
||||
nsresult RelativeFontChangeOnNode( PRInt32 aSizeChange,
|
||||
nsIDOMNode *aNode);
|
||||
|
||||
/* helper routines for node/parent manipulations */
|
||||
nsresult ReplaceContainer(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, const nsString &aNodeType);
|
||||
nsresult RemoveContainer(nsIDOMNode *inNode);
|
||||
nsresult InsertContainerAbove(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, const nsString &aNodeType);
|
||||
|
||||
|
||||
// Data members
|
||||
protected:
|
||||
|
||||
|
@ -150,7 +150,7 @@ nsTextEditRules::BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
||||
nsTextEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection, PRBool aSetSelection)
|
||||
{
|
||||
if (mLockRulesSniffing) return NS_OK;
|
||||
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
// nsEditRules methods
|
||||
NS_IMETHOD Init(nsHTMLEditor *aEditor, PRUint32 aFlags);
|
||||
NS_IMETHOD BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection);
|
||||
NS_IMETHOD AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection);
|
||||
NS_IMETHOD AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection, PRBool aSetSelection);
|
||||
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel, PRBool *aHandled);
|
||||
NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult);
|
||||
NS_IMETHOD GetFlags(PRUint32 *aFlags);
|
||||
|
@ -49,7 +49,7 @@ class nsEditRules
|
||||
public:
|
||||
NS_IMETHOD Init(nsHTMLEditor *aEditor, PRUint32 aFlags)=0;
|
||||
NS_IMETHOD BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection)=0;
|
||||
NS_IMETHOD AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)=0;
|
||||
NS_IMETHOD AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection, PRBool aSetSelection)=0;
|
||||
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel, PRBool *aHandled)=0;
|
||||
NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult)=0;
|
||||
NS_IMETHOD GetFlags(PRUint32 *aFlags)=0;
|
||||
|
@ -1787,7 +1787,7 @@ nsEditor::StartOperation(PRInt32 opID, nsIEditor::EDirection aDirection)
|
||||
/** All editor operations which alter the doc should be followed
|
||||
* with a call to EndOperation, naming the action and direction */
|
||||
NS_IMETHODIMP
|
||||
nsEditor::EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection)
|
||||
nsEditor::EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection, PRBool aSetSelection)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
@ -3304,22 +3304,41 @@ nsEditor::NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag)
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEditor::CanContainTag(nsIDOMNode* aParent, const nsString &aTag)
|
||||
nsEditor::CanContainTag(nsIDOMNode* aParent, const nsString &aChildTag)
|
||||
{
|
||||
// if we don't have a dtd then assume we can insert whatever want
|
||||
if (!mDTD) return PR_TRUE;
|
||||
|
||||
PRInt32 childTagEnum, parentTagEnum;
|
||||
nsAutoString parentStringTag;
|
||||
nsAutoString non_const_aTag(aTag);
|
||||
nsresult res = mDTD->StringTagToIntTag(non_const_aTag,&childTagEnum);
|
||||
if (NS_FAILED(res)) return PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> parentElement = do_QueryInterface(aParent);
|
||||
if (!parentElement) return PR_FALSE;
|
||||
|
||||
parentElement->GetTagName(parentStringTag);
|
||||
res = mDTD->StringTagToIntTag(parentStringTag,&parentTagEnum);
|
||||
return TagCanContainTag(parentStringTag, aChildTag);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEditor::TagCanContain(const nsString &aParentTag, nsIDOMNode* aChild)
|
||||
{
|
||||
nsAutoString childStringTag;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> childElement = do_QueryInterface(aChild);
|
||||
if (!childElement) return PR_FALSE;
|
||||
|
||||
childElement->GetTagName(childStringTag);
|
||||
return TagCanContainTag(aParentTag, childStringTag);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsEditor::TagCanContainTag(const nsString &aParentTag, const nsString &aChildTag)
|
||||
{
|
||||
// if we don't have a dtd then assume we can insert whatever want
|
||||
if (!mDTD) return PR_TRUE;
|
||||
|
||||
PRInt32 childTagEnum, parentTagEnum;
|
||||
nsAutoString non_const_childTag(aChildTag);
|
||||
nsAutoString non_const_parentTag(aParentTag);
|
||||
nsresult res = mDTD->StringTagToIntTag(non_const_childTag,&childTagEnum);
|
||||
if (NS_FAILED(res)) return PR_FALSE;
|
||||
res = mDTD->StringTagToIntTag(non_const_parentTag,&parentTagEnum);
|
||||
if (NS_FAILED(res)) return PR_FALSE;
|
||||
|
||||
return mDTD->CanContain(parentTagEnum, childTagEnum);
|
||||
|
@ -422,7 +422,7 @@ public:
|
||||
|
||||
/** All editor operations which alter the doc should be followed
|
||||
* with a call to EndOperation, naming the action and direction */
|
||||
NS_IMETHOD EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection);
|
||||
NS_IMETHOD EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection, PRBool aSetSelection);
|
||||
|
||||
/** return the string that represents text nodes in the content tree */
|
||||
static nsresult GetTextNodeTag(nsString& aOutString);
|
||||
@ -608,6 +608,8 @@ public:
|
||||
|
||||
/** returns PR_TRUE if aParent can contain a child of type aTag */
|
||||
PRBool CanContainTag(nsIDOMNode* aParent, const nsString &aTag);
|
||||
PRBool TagCanContain(const nsString &aParentTag, nsIDOMNode* aChild);
|
||||
PRBool TagCanContainTag(const nsString &aParentTag, const nsString &aChildTag);
|
||||
|
||||
/** returns PR_TRUE if aNode is a container */
|
||||
PRBool IsContainer(nsIDOMNode *aNode);
|
||||
|
@ -93,15 +93,16 @@ class nsAutoRules
|
||||
{
|
||||
public:
|
||||
|
||||
nsAutoRules(nsEditor *ed, PRInt32 action, nsIEditor::EDirection aDirection) :
|
||||
mEd(ed), mAction(action), mDirection(aDirection)
|
||||
nsAutoRules(nsEditor *ed, PRInt32 action, nsIEditor::EDirection aDirection, PRBool setSelection=PR_FALSE) :
|
||||
mEd(ed), mAction(action), mDirection(aDirection), mSetSelection(setSelection)
|
||||
{if (mEd) mEd->StartOperation(mAction, mDirection);}
|
||||
~nsAutoRules() {if (mEd) mEd->EndOperation(mAction, mDirection);}
|
||||
~nsAutoRules() {if (mEd) mEd->EndOperation(mAction, mDirection, mSetSelection);}
|
||||
|
||||
protected:
|
||||
nsEditor *mEd;
|
||||
PRInt32 mAction;
|
||||
nsIEditor::EDirection mDirection;
|
||||
PRBool mSetSelection;
|
||||
};
|
||||
|
||||
|
||||
|
@ -148,7 +148,7 @@ nsHTMLEditRules::BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
||||
nsHTMLEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection, PRBool aSetSelection)
|
||||
{
|
||||
if (mLockRulesSniffing) return NS_OK;
|
||||
|
||||
@ -172,8 +172,16 @@ nsHTMLEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
||||
nsAutoTxnsConserveSelection dontSpazMySelection(mEditor);
|
||||
|
||||
// expand the "changed doc range" as needed
|
||||
// MOOSE: I don't do this if the aSetSelection param is true. This is because
|
||||
// if aSetSelection is true, it means we are to set the selection to the changed
|
||||
// document region when we are done. So I need to preserve mDocChangeRange as is.
|
||||
// I should probably set up a parellel range for this purpose.
|
||||
|
||||
if (!aSetSelection)
|
||||
{
|
||||
res = PromoteRange(mDocChangeRange, action);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
// add in any needed <br>s, and remove any unneeded ones.
|
||||
res = AdjustSpecialBreaks();
|
||||
@ -208,6 +216,12 @@ nsHTMLEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
||||
nsCOMPtr<nsIPresShell> pres;
|
||||
mEditor->GetPresShell(getter_AddRefs(pres));
|
||||
if (pres) pres->SetCaretEnabled(PR_TRUE);
|
||||
|
||||
if (aSetSelection)
|
||||
{
|
||||
selection->ClearSelection();
|
||||
selection->AddRange(mDocChangeRange);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
@ -1100,7 +1114,7 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection,
|
||||
{
|
||||
// make a new ordered list, insert it where the current unordered list is,
|
||||
// and move all the children to the new list, and remove the old list
|
||||
res = ReplaceContainer(curNode,&newBlock,blockType);
|
||||
res = mEditor->ReplaceContainer(curNode,&newBlock,blockType);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curList = newBlock;
|
||||
continue;
|
||||
@ -1118,7 +1132,7 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection,
|
||||
{
|
||||
// make a new unordered list, insert it where the current ordered list is,
|
||||
// and move all the children to the new list, and remove the old list
|
||||
ReplaceContainer(curNode,&newBlock,blockType);
|
||||
mEditor->ReplaceContainer(curNode,&newBlock,blockType);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curList = newBlock;
|
||||
continue;
|
||||
@ -1179,11 +1193,11 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection,
|
||||
// don't wrap li around a paragraph. instead replace paragraph with li
|
||||
if (nsHTMLEditUtils::IsParagraph(curNode))
|
||||
{
|
||||
res = ReplaceContainer(curNode, &listItem, "li");
|
||||
res = mEditor->ReplaceContainer(curNode, &listItem, "li");
|
||||
}
|
||||
else
|
||||
{
|
||||
res = InsertContainerAbove(curNode, &listItem, "li");
|
||||
res = mEditor->InsertContainerAbove(curNode, &listItem, "li");
|
||||
}
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nsEditor::IsInlineNode(curNode))
|
||||
@ -1503,7 +1517,7 @@ nsHTMLEditRules::WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBoo
|
||||
{
|
||||
if (nsHTMLEditUtils::IsList(curNode)) // just unwrap this sublist
|
||||
{
|
||||
res = RemoveContainer(curNode);
|
||||
res = mEditor->RemoveContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else // we are moving a list item, but not whole list
|
||||
@ -1547,7 +1561,7 @@ nsHTMLEditRules::WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBoo
|
||||
{
|
||||
if (nsHTMLEditUtils::IsBlockquote(n))
|
||||
{
|
||||
RemoveContainer(n);
|
||||
mEditor->RemoveContainer(n);
|
||||
break;
|
||||
}
|
||||
n->GetParentNode(getter_AddRefs(tmp));
|
||||
@ -2347,142 +2361,6 @@ nsHTMLEditRules::MakeTransitionList(nsISupportsArray *inArrayOfNodes,
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ReplaceContainer: replace inNode with a new node (outNode) which is contructed
|
||||
// to be of type aNodeType. Put inNodes children into outNode.
|
||||
// Callers responsibility to make sure inNode's children can
|
||||
// go in outNode.
|
||||
nsresult
|
||||
nsHTMLEditRules::ReplaceContainer(nsIDOMNode *inNode,
|
||||
nsCOMPtr<nsIDOMNode> *outNode,
|
||||
const nsString &aNodeType)
|
||||
{
|
||||
if (!inNode || !outNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset;
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->CreateNode(aNodeType, parent, offset, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
PRBool bHasMoreChildren;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
offset = 0;
|
||||
while (bHasMoreChildren)
|
||||
{
|
||||
inNode->GetLastChild(getter_AddRefs(child));
|
||||
res = mEditor->DeleteNode(child);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->InsertNode(child, *outNode, 0);
|
||||
if (NS_FAILED(res)) return res;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
}
|
||||
res = mEditor->DeleteNode(inNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// RemoveContainer: remove inNode, reparenting it's children into their
|
||||
// the parent of inNode
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditRules::RemoveContainer(nsIDOMNode *inNode, PRBool aAddBRIfNeeded)
|
||||
{
|
||||
if (!inNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (nsHTMLEditUtils::IsBody(inNode))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset;
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// add BR's before and/or after the inNode
|
||||
// if aAddBRIfNeeded is set and if the content
|
||||
// before/after the node is inline.
|
||||
// Only do this if inNode is a block node.
|
||||
if (aAddBRIfNeeded && mEditor->IsBlockNode(inNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> nearNode, brNode;
|
||||
res = GetPriorHTMLSibling(inNode, &nearNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nearNode && mEditor->IsInlineNode(nearNode))
|
||||
{
|
||||
res = mEditor->CreateBR(parent, offset, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// refresh location info
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
res = GetNextHTMLSibling(inNode, &nearNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nearNode && mEditor->IsInlineNode(nearNode))
|
||||
{
|
||||
res = mEditor->CreateBR(parent, offset+1, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// refresh location info
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
|
||||
// loop through the child nodes of inNode and promote them
|
||||
// into inNode's parent.
|
||||
PRBool bHasMoreChildren;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
while (bHasMoreChildren)
|
||||
{
|
||||
inNode->GetLastChild(getter_AddRefs(child));
|
||||
res = mEditor->DeleteNode(child);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->InsertNode(child, parent, offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
}
|
||||
res = mEditor->DeleteNode(inNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// InsertContainerAbove: insert a new parent for inNode, returned in outNode,
|
||||
// which is contructed to be of type aNodeType. outNode becomes
|
||||
// a child of inNode's earlier parent.
|
||||
// Callers responsibility to make sure inNode's can be child
|
||||
// of outNode, and outNode can be child of old parent.
|
||||
nsresult
|
||||
nsHTMLEditRules::InsertContainerAbove(nsIDOMNode *inNode,
|
||||
nsCOMPtr<nsIDOMNode> *outNode,
|
||||
const nsString &aNodeType)
|
||||
{
|
||||
if (!inNode || !outNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset;
|
||||
res = nsEditor::GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// make new parent, outNode
|
||||
res = mEditor->CreateNode(aNodeType, parent, offset, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// put inNode in new parent, outNode
|
||||
res = mEditor->DeleteNode(inNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->InsertNode(inNode, *outNode, 0);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/********************************************************
|
||||
* main implementation methods
|
||||
@ -2558,7 +2436,7 @@ nsHTMLEditRules::ReturnInHeader(nsIDOMSelection *aSelection,
|
||||
}
|
||||
// else unwrap it
|
||||
nsCOMPtr<nsIDOMNode> newBlock;
|
||||
res = RemoveContainer(aHeader);
|
||||
res = mEditor->RemoveContainer(aHeader);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -2958,11 +2836,11 @@ nsHTMLEditRules::ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString
|
||||
// nsCOMPtr<nsIDOMNode> brNode;
|
||||
// res = mEditor->CreateBR(curParent, offset+1, &brNode);
|
||||
// if (NS_FAILED(res)) return res;
|
||||
res = RemoveContainer(curNode, PR_TRUE);
|
||||
res = mEditor->RemoveContainer(curNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = ReplaceContainer(curNode, &newBlock, *aBlockTag);
|
||||
res = mEditor->ReplaceContainer(curNode, &newBlock, *aBlockTag);
|
||||
}
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
@ -3743,7 +3621,7 @@ nsHTMLEditRules::PopListItem(nsIDOMNode *aListItem, PRBool *aOutOfList)
|
||||
nsCOMPtr<nsIDOMNode> lastChild;
|
||||
res = GetLastEditableChild(curNode, &lastChild);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = RemoveContainer(curNode);
|
||||
res = mEditor->RemoveContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (mEditor->IsInlineNode(lastChild))
|
||||
{
|
||||
@ -4003,15 +3881,9 @@ nsHTMLEditListener::DidSplitNode(nsIDOMNode *aExistingRightNode,
|
||||
nsresult aResult)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
nsresult res = MakeRangeFromNode(aNewLeftNode, &range);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (range)
|
||||
{
|
||||
// now extend range to include right node
|
||||
res = range->SetEndAfter(aExistingRightNode);
|
||||
nsresult res = MakeCollapsedRange(aExistingRightNode, 0, &range);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mRules->UpdateDocChangeRange(range);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -4019,7 +3891,9 @@ nsHTMLEditListener::DidSplitNode(nsIDOMNode *aExistingRightNode,
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditListener::WillJoinNodes(nsIDOMNode *aLeftNode, nsIDOMNode *aRightNode, nsIDOMNode *aParent)
|
||||
{
|
||||
return NS_OK;
|
||||
// remember split point
|
||||
nsresult res = nsEditor::GetLengthOfDOMNode(aLeftNode, mJoinOffset);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@ -4029,14 +3903,11 @@ nsHTMLEditListener::DidJoinNodes(nsIDOMNode *aLeftNode,
|
||||
nsIDOMNode *aParent,
|
||||
nsresult aResult)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
// assumption that Join keeps the righthand node
|
||||
nsresult res = MakeRangeFromNode(aRightNode, &range);
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
nsresult res = MakeCollapsedRange(aRightNode, mJoinOffset, &range);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (range)
|
||||
{
|
||||
res = mRules->UpdateDocChangeRange(range);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -4143,6 +4014,28 @@ nsHTMLEditListener::MakeRangeFromNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMRange>
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditListener::MakeCollapsedRange(nsIDOMNode *inNode, PRInt32 inOffset, nsCOMPtr<nsIDOMRange> *outRange)
|
||||
{
|
||||
if (!inNode || !outRange) return NS_ERROR_NULL_POINTER;
|
||||
*outRange = nsnull;
|
||||
|
||||
// first check that inNode is still a descendant of the body
|
||||
if (!IsDescendantOfBody(inNode)) return NS_OK;
|
||||
|
||||
// construct a range to represent start and end of inNode
|
||||
nsresult res = nsComponentManager::CreateInstance(kRangeCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIDOMRange),
|
||||
getter_AddRefs(*outRange));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = (*outRange)->SetStart(inNode, inOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = (*outRange)->SetEnd(inNode, inOffset);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditListener::MakeRangeFromTextOffsets(nsIDOMCharacterData *inNode,
|
||||
PRInt32 inStart,
|
||||
|
@ -42,7 +42,7 @@ public:
|
||||
|
||||
// nsEditRules methods
|
||||
NS_IMETHOD BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection);
|
||||
NS_IMETHOD AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection);
|
||||
NS_IMETHOD AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection, PRBool aSetSelection);
|
||||
NS_IMETHOD Init(nsHTMLEditor *aEditor, PRUint32 aFlags);
|
||||
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel, PRBool *aHandled);
|
||||
NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult);
|
||||
@ -111,10 +111,6 @@ protected:
|
||||
nsresult ShouldMakeEmptyBlock(nsIDOMSelection *aSelection, const nsString *blockTag, PRBool *outMakeEmpty);
|
||||
nsresult ApplyBlockStyle(nsISupportsArray *arrayOfNodes, const nsString *aBlockTag);
|
||||
|
||||
nsresult ReplaceContainer(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, const nsString &aNodeType);
|
||||
nsresult RemoveContainer(nsIDOMNode *inNode, PRBool aAddBRIfNeeded=PR_FALSE);
|
||||
nsresult InsertContainerAbove(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, const nsString &aNodeType);
|
||||
|
||||
nsresult JoinNodesSmart( nsIDOMNode *aNodeLeft,
|
||||
nsIDOMNode *aNodeRight,
|
||||
nsCOMPtr<nsIDOMNode> *aOutMergeParent,
|
||||
@ -189,12 +185,14 @@ protected:
|
||||
PRInt32 inStart,
|
||||
PRInt32 inEnd,
|
||||
nsCOMPtr<nsIDOMRange> *outRange);
|
||||
nsresult MakeCollapsedRange(nsIDOMNode *inNode, PRInt32 inOffset, nsCOMPtr<nsIDOMRange> *outRange);
|
||||
PRBool IsDescendantOfBody(nsIDOMNode *inNode) ;
|
||||
|
||||
// data members
|
||||
nsHTMLEditor *mEditor;
|
||||
nsHTMLEditRules *mRules;
|
||||
nsCOMPtr<nsIDOMNode> mBody;
|
||||
PRUint32 mJoinOffset; // need to remember an int across willJoin/didJoin...
|
||||
};
|
||||
|
||||
#endif //nsHTMLEditRules_h__
|
||||
|
@ -68,6 +68,42 @@ nsHTMLEditUtils::IsBreak(nsIDOMNode *node)
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBreak: true if node an html break node
|
||||
//
|
||||
PRBool
|
||||
nsHTMLEditUtils::IsBig(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsHTMLEditUtils::IsBig");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "big")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBreak: true if node an html break node
|
||||
//
|
||||
PRBool
|
||||
nsHTMLEditUtils::IsSmall(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsHTMLEditUtils::IsSmall");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "small")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsMozBR: true if node an html br node with type = _moz
|
||||
//
|
||||
|
@ -34,6 +34,8 @@ public:
|
||||
// from nsTextEditRules:
|
||||
static PRBool IsBody(nsIDOMNode *aNode);
|
||||
static PRBool IsBreak(nsIDOMNode *aNode);
|
||||
static PRBool IsBig(nsIDOMNode *aNode);
|
||||
static PRBool IsSmall(nsIDOMNode *aNode);
|
||||
static PRBool IsMozBR(nsIDOMNode *aNode);
|
||||
static PRBool HasMozAttr(nsIDOMNode *aNode);
|
||||
static PRBool InBody(nsIDOMNode *aNode);
|
||||
|
@ -102,6 +102,7 @@ static NS_DEFINE_CID(kCNavDTDCID, NS_CNAVDTD_CID);
|
||||
|
||||
static NS_DEFINE_CID(kHTMLEditorCID, NS_HTMLEDITOR_CID);
|
||||
static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID);
|
||||
static NS_DEFINE_IID(kSubtreeIteratorCID, NS_SUBTREEITERATOR_CID);
|
||||
static NS_DEFINE_CID(kCRangeCID, NS_RANGE_CID);
|
||||
static NS_DEFINE_IID(kFileWidgetCID, NS_FILEWIDGET_CID);
|
||||
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
|
||||
@ -1341,14 +1342,12 @@ NS_IMETHODIMP nsHTMLEditor::RemoveInlineProperty(nsIAtom *aProperty, const nsStr
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::IncreaseFontSize()
|
||||
{
|
||||
//TODO: Write this!
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return RelativeFontChange(1);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::DecreaseFontSize()
|
||||
{
|
||||
//TODO: Write this!
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
return RelativeFontChange(-1);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::GetTypingState(nsIAtom *aProperty, PRBool &aPropIsSet, PRBool &aSetting)
|
||||
@ -4512,11 +4511,11 @@ nsHTMLEditor::StartOperation(PRInt32 opID, nsIEditor::EDirection aDirection)
|
||||
/** All editor operations which alter the doc should be followed
|
||||
* with a call to EndOperation, naming the action and direction */
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection)
|
||||
nsHTMLEditor::EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection, PRBool aSetSelection)
|
||||
{
|
||||
if (! ((opID==kOpInsertText) || (opID==kOpInsertIMEText)) )
|
||||
ClearInlineStylesCache();
|
||||
if (mRules) return mRules->AfterEdit(opID, aDirection);
|
||||
if (mRules) return mRules->AfterEdit(opID, aDirection, aSetSelection);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -7213,7 +7212,7 @@ nsHTMLEditor::CollapseAdjacentTextNodes(nsIDOMSelection *aInSelection)
|
||||
{
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
nsCOMPtr<nsIContentIterator> iter;
|
||||
result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull,
|
||||
result = nsComponentManager::CreateInstance(kSubtreeIteratorCID, nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(iter));
|
||||
if (NS_FAILED(result)) return result;
|
||||
@ -7376,3 +7375,368 @@ nsHTMLEditor::GetNextElementByTagName(nsIDOMElement *aCurrentElement,
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::RelativeFontChange( PRInt32 aSizeChange)
|
||||
{
|
||||
// Can only change font size by + or - 1
|
||||
if ( !( (aSizeChange==1) || (aSizeChange==-1) ) )
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
ForceCompositionEnd();
|
||||
|
||||
// wrap with txn batching, rules sniffing, and selection preservation code
|
||||
nsAutoEditBatch batchIt(this);
|
||||
nsAutoRules beginRulesSniffing(this, kOpSetTextProperty, nsIEditor::eNext, PR_TRUE);
|
||||
|
||||
// Get the selection
|
||||
nsCOMPtr<nsIDOMSelection>selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!selection) return NS_ERROR_FAILURE;
|
||||
|
||||
// Is the selection collapsed?
|
||||
PRBool bCollapsed;
|
||||
res = selection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's collapsed dont do anything.
|
||||
// MOOSE: We should probably have typing state for this like
|
||||
// we do for other things.
|
||||
if (bCollapsed)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// get selection range enumerator
|
||||
nsCOMPtr<nsIEnumerator> enumerator;
|
||||
res = selection->GetEnumerator(getter_AddRefs(enumerator));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!enumerator) return NS_ERROR_FAILURE;
|
||||
|
||||
// loop thru the ranges in the selection
|
||||
enumerator->First();
|
||||
nsCOMPtr<nsISupports> currentItem;
|
||||
while ((NS_ENUMERATOR_FALSE == enumerator->IsDone()))
|
||||
{
|
||||
res = enumerator->CurrentItem(getter_AddRefs(currentItem));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!currentItem) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
|
||||
// check for easy case: both range endpoints in same text node
|
||||
nsCOMPtr<nsIDOMNode> startNode, endNode;
|
||||
res = range->GetStartParent(getter_AddRefs(startNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = range->GetEndParent(getter_AddRefs(endNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if ((startNode == endNode) && IsTextNode(startNode))
|
||||
{
|
||||
PRInt32 startOffset, endOffset;
|
||||
range->GetStartOffset(&startOffset);
|
||||
range->GetEndOffset(&endOffset);
|
||||
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(startNode);
|
||||
res = RelativeFontChangeOnTextNode(aSizeChange, nodeAsText, startOffset, endOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// not the easy case. range not contained in single text node.
|
||||
// there are up to three phases here. There are all the nodes
|
||||
// reported by the subtree iterator to be processed. And there
|
||||
// are potentially a starting textnode and an ending textnode
|
||||
// which are only partially contained by the range.
|
||||
|
||||
// lets handle the nodes reported by the iterator. These nodes
|
||||
// are entirely contained in the selection range. We build up
|
||||
// a list of them (since doing operations on the document during
|
||||
// iteration would perturb the iterator).
|
||||
|
||||
nsCOMPtr<nsIContentIterator> iter;
|
||||
res = nsComponentManager::CreateInstance(kSubtreeIteratorCID, nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(iter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!iter) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISupportsArray> arrayOfNodes;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
|
||||
// make a array
|
||||
res = NS_NewISupportsArray(getter_AddRefs(arrayOfNodes));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// iterate range and build up array
|
||||
iter->Init(range);
|
||||
while (NS_ENUMERATOR_FALSE == iter->IsDone())
|
||||
{
|
||||
res = iter->CurrentNode(getter_AddRefs(content));
|
||||
if (NS_FAILED(res)) return res;
|
||||
node = do_QueryInterface(content);
|
||||
if (!node) return NS_ERROR_FAILURE;
|
||||
isupports = do_QueryInterface(node);
|
||||
arrayOfNodes->AppendElement(isupports);
|
||||
res = iter->Next();
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
// now that we have the list, do the font size change on each node
|
||||
PRUint32 listCount;
|
||||
PRInt32 j;
|
||||
arrayOfNodes->Count(&listCount);
|
||||
for (j = 0; j < listCount; j++)
|
||||
{
|
||||
isupports = (dont_AddRef)(arrayOfNodes->ElementAt(0));
|
||||
node = do_QueryInterface(isupports);
|
||||
res = RelativeFontChangeOnNode(aSizeChange, node);
|
||||
if (NS_FAILED(res)) return res;
|
||||
arrayOfNodes->RemoveElementAt(0);
|
||||
}
|
||||
|
||||
// now check the start and end parents of the range to see if they need to
|
||||
// be seperately handled (they do if they are text nodes, due to how the
|
||||
// subtree iterator works - it will not have reported them).
|
||||
if (IsTextNode(startNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(startNode);
|
||||
PRInt32 startOffset;
|
||||
PRUint32 textLen;
|
||||
range->GetStartOffset(&startOffset);
|
||||
nodeAsText->GetLength(&textLen);
|
||||
res = RelativeFontChangeOnTextNode(aSizeChange, nodeAsText, startOffset, textLen);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
if (IsTextNode(endNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(endNode);
|
||||
PRInt32 endOffset;
|
||||
range->GetEndOffset(&endOffset);
|
||||
res = RelativeFontChangeOnTextNode(aSizeChange, nodeAsText, 0, endOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
enumerator->Next();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::RelativeFontChangeOnTextNode( PRInt32 aSizeChange,
|
||||
nsIDOMCharacterData *aTextNode,
|
||||
PRInt32 aStartOffset,
|
||||
PRInt32 aEndOffset)
|
||||
{
|
||||
// Can only change font size by + or - 1
|
||||
if ( !( (aSizeChange==1) || (aSizeChange==-1) ) )
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
if (!aTextNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// dont need to do anything if no characters actually selected
|
||||
if (aStartOffset == aEndOffset) return NS_OK;
|
||||
|
||||
nsresult res = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> tmp, node = do_QueryInterface(aTextNode);
|
||||
|
||||
// do we need to split the text node?
|
||||
PRUint32 textLen;
|
||||
aTextNode->GetLength(&textLen);
|
||||
|
||||
if ( aEndOffset != textLen )
|
||||
{
|
||||
// we need to split off back of text node
|
||||
res = SplitNode(node, aEndOffset, getter_AddRefs(tmp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
node = tmp; // remember left node
|
||||
}
|
||||
if ( aStartOffset )
|
||||
{
|
||||
// we need to split off front of text node
|
||||
res = SplitNode(node, aStartOffset, getter_AddRefs(tmp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
// reparent the node inside font node with appropriate relative size
|
||||
nsAutoString tag;
|
||||
if (aSizeChange == 1) tag = "big";
|
||||
else tag = "small";
|
||||
res = InsertContainerAbove(node, &tmp, tag);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::RelativeFontChangeOnNode( PRInt32 aSizeChange,
|
||||
nsIDOMNode *aNode)
|
||||
{
|
||||
// Can only change font size by + or - 1
|
||||
if ( !( (aSizeChange==1) || (aSizeChange==-1) ) )
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
if (!aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult res = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
nsAutoString tag;
|
||||
if (aSizeChange == 1) tag = "big";
|
||||
else tag = "small";
|
||||
|
||||
// is this node a text node?
|
||||
if (IsTextNode(aNode))
|
||||
{
|
||||
res = InsertContainerAbove(aNode, &tmp, tag);
|
||||
return res;
|
||||
}
|
||||
// is it the opposite of what we want?
|
||||
if ( ((aSizeChange == 1) && nsHTMLEditUtils::IsSmall(aNode)) ||
|
||||
((aSizeChange == -1) && nsHTMLEditUtils::IsBig(aNode)) )
|
||||
{
|
||||
// in that case, just remove this node and pull up the children
|
||||
res = RemoveContainer(aNode);
|
||||
return res;
|
||||
}
|
||||
// can it be put inside a "big" or "small"?
|
||||
if (TagCanContain(tag, aNode))
|
||||
{
|
||||
// ok, chuck it in.
|
||||
res = InsertContainerAbove(aNode, &tmp, tag);
|
||||
return res;
|
||||
}
|
||||
// none of the above? then cycle through the children.
|
||||
// MOOSE: we should group the children together if possible
|
||||
// into a single "big" or "small". For the moment they are
|
||||
// each getting their own.
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
res = aNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (childNodes)
|
||||
{
|
||||
PRInt32 j;
|
||||
PRUint32 childCount;
|
||||
childNodes->GetLength(&childCount);
|
||||
for (j=0 ; j<childCount; j++)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
res = childNodes->Item(j, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(res)) && (childNode))
|
||||
{
|
||||
res = RelativeFontChangeOnNode(aSizeChange, childNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ReplaceContainer: replace inNode with a new node (outNode) which is contructed
|
||||
// to be of type aNodeType. Put inNodes children into outNode.
|
||||
// Callers responsibility to make sure inNode's children can
|
||||
// go in outNode.
|
||||
nsresult
|
||||
nsHTMLEditor::ReplaceContainer(nsIDOMNode *inNode,
|
||||
nsCOMPtr<nsIDOMNode> *outNode,
|
||||
const nsString &aNodeType)
|
||||
{
|
||||
if (!inNode || !outNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset;
|
||||
res = GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = CreateNode(aNodeType, parent, offset, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
PRBool bHasMoreChildren;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
offset = 0;
|
||||
while (bHasMoreChildren)
|
||||
{
|
||||
inNode->GetLastChild(getter_AddRefs(child));
|
||||
res = DeleteNode(child);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = InsertNode(child, *outNode, 0);
|
||||
if (NS_FAILED(res)) return res;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
}
|
||||
res = DeleteNode(inNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// RemoveContainer: remove inNode, reparenting it's children into their
|
||||
// the parent of inNode
|
||||
//
|
||||
nsresult
|
||||
nsHTMLEditor::RemoveContainer(nsIDOMNode *inNode)
|
||||
{
|
||||
if (!inNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (nsHTMLEditUtils::IsBody(inNode))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset;
|
||||
res = GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// loop through the child nodes of inNode and promote them
|
||||
// into inNode's parent.
|
||||
PRBool bHasMoreChildren;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
while (bHasMoreChildren)
|
||||
{
|
||||
inNode->GetLastChild(getter_AddRefs(child));
|
||||
res = DeleteNode(child);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = InsertNode(child, parent, offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
}
|
||||
res = DeleteNode(inNode);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// InsertContainerAbove: insert a new parent for inNode, returned in outNode,
|
||||
// which is contructed to be of type aNodeType. outNode becomes
|
||||
// a child of inNode's earlier parent.
|
||||
// Callers responsibility to make sure inNode's can be child
|
||||
// of outNode, and outNode can be child of old parent.
|
||||
nsresult
|
||||
nsHTMLEditor::InsertContainerAbove(nsIDOMNode *inNode,
|
||||
nsCOMPtr<nsIDOMNode> *outNode,
|
||||
const nsString &aNodeType)
|
||||
{
|
||||
if (!inNode || !outNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsresult res;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset;
|
||||
res = GetNodeLocation(inNode, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// make new parent, outNode
|
||||
res = CreateNode(aNodeType, parent, offset, getter_AddRefs(*outNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// put inNode in new parent, outNode
|
||||
res = DeleteNode(inNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = InsertNode(inNode, *outNode, 0);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -260,7 +260,7 @@ public:
|
||||
|
||||
/** All editor operations which alter the doc should be followed
|
||||
* with a call to EndOperation, naming the action and direction */
|
||||
NS_IMETHOD EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection);
|
||||
NS_IMETHOD EndOperation(PRInt32 opID, nsIEditor::EDirection aDirection, PRBool aSetSelection);
|
||||
|
||||
/** returns PR_TRUE if aParent can contain a child of type aTag */
|
||||
PRBool CanContainTag(nsIDOMNode* aParent, const nsString &aTag);
|
||||
@ -546,6 +546,23 @@ protected:
|
||||
/* small utility routine to test the eEditorReadonly bit */
|
||||
PRBool IsModifiable();
|
||||
|
||||
/* increase/decrease the font size of selection */
|
||||
nsresult RelativeFontChange( PRInt32 aSizeChange);
|
||||
|
||||
/* helper routines for font size changing */
|
||||
nsresult RelativeFontChangeOnTextNode( PRInt32 aSizeChange,
|
||||
nsIDOMCharacterData *aTextNode,
|
||||
PRInt32 aStartOffset,
|
||||
PRInt32 aEndOffset);
|
||||
nsresult RelativeFontChangeOnNode( PRInt32 aSizeChange,
|
||||
nsIDOMNode *aNode);
|
||||
|
||||
/* helper routines for node/parent manipulations */
|
||||
nsresult ReplaceContainer(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, const nsString &aNodeType);
|
||||
nsresult RemoveContainer(nsIDOMNode *inNode);
|
||||
nsresult InsertContainerAbove(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNode, const nsString &aNodeType);
|
||||
|
||||
|
||||
// Data members
|
||||
protected:
|
||||
|
||||
|
@ -150,7 +150,7 @@ nsTextEditRules::BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
||||
nsTextEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection, PRBool aSetSelection)
|
||||
{
|
||||
if (mLockRulesSniffing) return NS_OK;
|
||||
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
// nsEditRules methods
|
||||
NS_IMETHOD Init(nsHTMLEditor *aEditor, PRUint32 aFlags);
|
||||
NS_IMETHOD BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection);
|
||||
NS_IMETHOD AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection);
|
||||
NS_IMETHOD AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection, PRBool aSetSelection);
|
||||
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel, PRBool *aHandled);
|
||||
NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult);
|
||||
NS_IMETHOD GetFlags(PRUint32 *aFlags);
|
||||
|
Loading…
Reference in New Issue
Block a user