diff --git a/mozilla/editor/base/JoinElementTxn.cpp b/mozilla/editor/base/JoinElementTxn.cpp index c12a638480f..4efa9caf8f6 100644 --- a/mozilla/editor/base/JoinElementTxn.cpp +++ b/mozilla/editor/base/JoinElementTxn.cpp @@ -90,7 +90,7 @@ NS_IMETHODIMP JoinElementTxn::Do(void) result = editor->JoinNodesImpl(mRightNode, mLeftNode, mParent, PR_FALSE); if (NS_SUCCEEDED(result)) { - if (gNoisy) { printf(" left node = %p removed\n", this, mLeftNode.get()); } + if (gNoisy) { printf(" left node = %p removed\n", mLeftNode.get()); } nsCOMPtrselection; mEditor->GetSelection(getter_AddRefs(selection)); if (selection) diff --git a/mozilla/editor/base/nsTextEditRules.cpp b/mozilla/editor/base/nsTextEditRules.cpp index 668c2a205a2..3266ac91bfd 100644 --- a/mozilla/editor/base/nsTextEditRules.cpp +++ b/mozilla/editor/base/nsTextEditRules.cpp @@ -286,7 +286,7 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta InsertStyleNode(newTextNode, nsIEditProperty::b, aSelection); } else { - printf("not yet implemented, make unbold in a bold context\n"); + printf("not yet implemented, make not bold in a bold context\n"); } } if (aTypeInState.IsSet(NS_TYPEINSTATE_ITALIC)) @@ -296,7 +296,7 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta } else { - printf("not yet implemented, make unitalic in a italic context\n"); + printf("not yet implemented, make not italic in a italic context\n"); } } if (aTypeInState.IsSet(NS_TYPEINSTATE_UNDERLINE)) @@ -334,21 +334,20 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta { // now we've got the body tag. insert the style tag if (aTypeInState.IsSet(NS_TYPEINSTATE_BOLD)) { - if (PR_TRUE==aTypeInState.GetBold()) - { // make the next char bold - nsAutoString tag; - nsIEditProperty::b->ToString(tag); - nsCOMPtrnewStyleNode; - nsCOMPtrnewTextNode; - result = mEditor->CreateNode(tag, bodyNode, 0, getter_AddRefs(newStyleNode)); - if (NS_SUCCEEDED(result)) - { - result = mEditor->CreateNode(nsIEditor::GetTextNodeTag(), newStyleNode, 0, getter_AddRefs(newTextNode)); - if (NS_SUCCEEDED(result)) - { - aSelection->Collapse(newTextNode, 0); - } - } + if (PR_TRUE==aTypeInState.GetBold()) { + InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::b, aSelection); + } + } + if (aTypeInState.IsSet(NS_TYPEINSTATE_ITALIC)) + { + if (PR_TRUE==aTypeInState.GetItalic()) { + InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::i, aSelection); + } + } + if (aTypeInState.IsSet(NS_TYPEINSTATE_UNDERLINE)) + { + if (PR_TRUE==aTypeInState.GetUnderline()) { + InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::u, aSelection); } } } @@ -389,6 +388,50 @@ nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode, nsIAtom *aTag, nsIDOMSelecti } +NS_IMETHODIMP +nsTextEditRules::InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTag, nsIDOMSelection *aSelection) +{ + NS_ASSERTION(aParentNode && aTag, "bad args"); + if (!aParentNode || !aTag) { return NS_ERROR_NULL_POINTER; } + + nsresult result; + // if the selection already points to a text node, just call InsertStyleNode() + if (aSelection) + { + nsCOMPtranchor; + PRInt32 offset; + nsresult result = aSelection->GetAnchorNodeAndOffset(getter_AddRefs(anchor), &offset); + if ((NS_SUCCEEDED(result)) && anchor) + { + nsCOMPtranchorAsText; + anchorAsText = do_QueryInterface(anchor); + if (anchorAsText) + { + result = InsertStyleNode(anchor, aTag, aSelection); + return result; + } + } + } + // if we get here, there is no selected text node so we create one. + nsAutoString tag; + aTag->ToString(tag); + nsCOMPtrnewStyleNode; + nsCOMPtrnewTextNode; + result = mEditor->CreateNode(tag, aParentNode, 0, getter_AddRefs(newStyleNode)); + if (NS_SUCCEEDED(result)) + { + result = mEditor->CreateNode(nsIEditor::GetTextNodeTag(), newStyleNode, 0, getter_AddRefs(newTextNode)); + if (NS_SUCCEEDED(result)) + { + if (aSelection) { + aSelection->Collapse(newTextNode, 0); + } + } + } + return result; +} + + /* NS_IMETHODIMP nsTextEditRules::GetInsertBreakTag(nsIAtom **aTag) @@ -529,6 +572,7 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul nsCOMPtr parentNode; selectedNode->GetParentNode(getter_AddRefs(parentNode)); result = mEditor->JoinNodes(siblingNode, selectedNode, parentNode); + // selectedNode will remain after the join, siblingNode is removed } } selectedNode->GetNextSibling(getter_AddRefs(siblingNode)); @@ -543,8 +587,9 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul nsCOMPtr parentNode; selectedNode->GetParentNode(getter_AddRefs(parentNode)); result = mEditor->JoinNodes(selectedNode, siblingNode, parentNode); + // selectedNode will remain after the join, siblingNode is removed // set selection - aSelection->Collapse(selectedNode, selectedNodeLength); + aSelection->Collapse(siblingNode, selectedNodeLength); } } } diff --git a/mozilla/editor/base/nsTextEditRules.h b/mozilla/editor/base/nsTextEditRules.h index 18399280ea7..80a27f5647b 100644 --- a/mozilla/editor/base/nsTextEditRules.h +++ b/mozilla/editor/base/nsTextEditRules.h @@ -89,7 +89,19 @@ protected: * aSelection is optional. If provided, aSelection is set to (aNode, 0) * if aNode was successfully placed in a new style node */ - NS_IMETHOD InsertStyleNode(nsIDOMNode *aNode, nsIAtom *aTag, nsIDOMSelection *aSelection); + NS_IMETHOD InsertStyleNode(nsIDOMNode *aNode, + nsIAtom *aTag, + nsIDOMSelection *aSelection); + + /** create a new style node of type aTag in aParentNode, and put a new text node + * in the new style node. + * If aSelection is provided and points to a text node, just call InsertStyleNode instead. + * aSelection is optional. If provided, aSelection is set to (newTextNode, 0) + * if newTextNode was successfully created. + */ + NS_IMETHOD InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, + nsIAtom *aTag, + nsIDOMSelection *aSelection); // data nsTextEditor *mEditor; // note that we do not refcount the editor diff --git a/mozilla/editor/base/nsTextEditor.cpp b/mozilla/editor/base/nsTextEditor.cpp index fef57eeafa9..1a19afad846 100644 --- a/mozilla/editor/base/nsTextEditor.cpp +++ b/mozilla/editor/base/nsTextEditor.cpp @@ -97,7 +97,7 @@ static NS_DEFINE_IID(kIContentIteratorIID, NS_ICONTENTITERTOR_IID); static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID); #ifdef NS_DEBUG -static PRBool gNoisy = PR_FALSE; +static PRBool gNoisy = PR_TRUE; #else static const PRBool gNoisy = PR_FALSE; #endif @@ -1350,6 +1350,7 @@ nsTextEditor::SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange, } } + // create a style node for the text in the start parent nsCOMPtrnodeAsChar; nodeAsChar = do_QueryInterface(aStartNode); if (!nodeAsChar) @@ -1381,106 +1382,81 @@ NS_IMETHODIMP nsTextEditor::RemoveTextPropertiesForNode(nsIDOMNode *aNode, nsresult result=NS_OK; nsCOMPtrnodeAsChar; nodeAsChar = do_QueryInterface(aNode); - if (!nodeAsChar) - return NS_ERROR_FAILURE; - + PRBool insertAfter=PR_FALSE; PRBool textPropertySet; IsTextPropertySetByContent(aNode, aPropName, textPropertySet); if (PR_TRUE==textPropertySet) { + nsCOMPtrparent; // initially set to first interior parent node to process + nsCOMPtrnewMiddleNode; // this will be the middle node after any required splits + nsCOMPtrnewLeftNode; // this will be the leftmost node, + // the node being split will be rightmost PRUint32 count; - nodeAsChar->GetLength(&count); - // split the node, and all parent nodes up to the style node - // then promote the selected content to the parent of the style node - nsCOMPtrnewLeftNode; // this will be the leftmost node, - // the node being split will be rightmost - if (0!=aStartOffset) { - printf("* splitting text node %p at %d\n", aNode, aStartOffset); - result = nsEditor::SplitNode(aNode, aStartOffset, getter_AddRefs(newLeftNode)); - printf("* split created left node %p\n", newLeftNode.get()); - if (gNoisy) {DebugDumpContent(); } // DEBUG - } - if (NS_SUCCEEDED(result)) + // if aNode is a text node, treat is specially + if (nodeAsChar) { - nsCOMPtrnewMiddleNode; // this will be the middle node - if ((PRInt32)count!=aEndOffset) { - printf("* splitting text node (right node) %p at %d\n", aNode, aEndOffset-aStartOffset); - result = nsEditor::SplitNode(aNode, aEndOffset-aStartOffset, getter_AddRefs(newMiddleNode)); - printf("* split created middle node %p\n", newMiddleNode.get()); + nodeAsChar->GetLength(&count); + // split the node, and all parent nodes up to the style node + // then promote the selected content to the parent of the style node + if (0!=aStartOffset) { + printf("* splitting text node %p at %d\n", aNode, aStartOffset); + result = nsEditor::SplitNode(aNode, aStartOffset, getter_AddRefs(newLeftNode)); + printf("* split created left node %p\n", newLeftNode.get()); if (gNoisy) {DebugDumpContent(); } // DEBUG } - else { - printf("* no need to split text node\n"); - newMiddleNode = do_QueryInterface(aNode); - } - NS_ASSERTION(newMiddleNode, "no middle node created"); - // now that the text node is split, split parent nodes until we get to the style node - nsCOMPtrparent; - parent = do_QueryInterface(aParent); // we know this has to succeed, no need to check - if (NS_SUCCEEDED(result) && newMiddleNode) + if (NS_SUCCEEDED(result)) { - // split every ancestor until we find the node that is giving us the style we want to remove - // then split the style node and promote the selected content to the style node's parent - while (NS_SUCCEEDED(result) && parent) + if ((PRInt32)count!=aEndOffset) { + printf("* splitting text node (right node) %p at %d\n", aNode, aEndOffset-aStartOffset); + result = nsEditor::SplitNode(aNode, aEndOffset-aStartOffset, getter_AddRefs(newMiddleNode)); + printf("* split created middle node %p\n", newMiddleNode.get()); + if (gNoisy) {DebugDumpContent(); } // DEBUG + } + else { + printf("* no need to split text node\n"); + newMiddleNode = do_QueryInterface(aNode); + insertAfter = PR_TRUE; + } + NS_ASSERTION(newMiddleNode, "no middle node created"); + // now that the text node is split, split parent nodes until we get to the style node + parent = do_QueryInterface(aParent); // we know this has to succeed, no need to check + } + } + else { + newMiddleNode = do_QueryInterface(aNode); + parent = do_QueryInterface(aParent); + } + if (NS_SUCCEEDED(result) && newMiddleNode) + { + // split every ancestor until we find the node that is giving us the style we want to remove + // then split the style node and promote the selected content to the style node's parent + while (NS_SUCCEEDED(result) && parent) + { + printf("* looking at parent %p\n", parent); + // get the tag from parent and see if we're done + nsCOMPtrtemp; + nsCOMPtrelement; + element = do_QueryInterface(parent); + if (element) { - printf("* looking at parent %p\n", parent); - // get the tag from parent and see if we're done - nsCOMPtrtemp; - nsCOMPtrelement; - element = do_QueryInterface(parent); - if (element) + nsAutoString tag; + result = element->GetTagName(tag); + printf("* parent has tag %s\n", tag.ToNewCString()); // leak! + if (NS_SUCCEEDED(result)) { - nsAutoString tag; - result = element->GetTagName(tag); - printf("* parent has tag %s\n", tag.ToNewCString()); // leak! - if (NS_SUCCEEDED(result)) + if (PR_FALSE==tag.Equals(aPropName)) { - if (PR_FALSE==tag.Equals(aPropName)) + printf("* this is not the style node\n"); + PRInt32 offsetInParent; + result = nsIEditorSupport::GetChildOffset(newMiddleNode, parent, offsetInParent); + if (NS_SUCCEEDED(result)) { - printf("* this is not the style node\n"); - PRInt32 offsetInParent; - result = nsIEditorSupport::GetChildOffset(newMiddleNode, parent, offsetInParent); - if (NS_SUCCEEDED(result)) - { - if (0!=offsetInParent) { - printf("* splitting parent %p at offset %d\n", parent, offsetInParent); - result = nsEditor::SplitNode(parent, offsetInParent, getter_AddRefs(newLeftNode)); - printf("* split created left node %p sibling of parent\n", newLeftNode.get()); - if (gNoisy) {DebugDumpContent(); } // DEBUG - } - if (NS_SUCCEEDED(result)) - { - nsCOMPtrchildNodes; - result = parent->GetChildNodes(getter_AddRefs(childNodes)); - if (NS_SUCCEEDED(result) && childNodes) - { - childNodes->GetLength(&count); - NS_ASSERTION(count>0, "bad child count in newly split node"); - if ((PRInt32)count!=1) - { - printf("* splitting parent %p at offset %d\n", parent, 1); - result = nsEditor::SplitNode(parent, 1, getter_AddRefs(newMiddleNode)); - printf("* split created middle node %p sibling of parent\n", newMiddleNode.get()); - if (gNoisy) {DebugDumpContent(); } // DEBUG - } - else { - printf("* no need to split parent, newMiddleNode=parent\n"); - newMiddleNode = do_QueryInterface(parent); - } - NS_ASSERTION(newMiddleNode, "no middle node created"); - parent->GetParentNode(getter_AddRefs(temp)); - parent = do_QueryInterface(temp); - } - } + if (0!=offsetInParent) { + printf("* splitting parent %p at offset %d\n", parent, offsetInParent); + result = nsEditor::SplitNode(parent, offsetInParent, getter_AddRefs(newLeftNode)); + printf("* split created left node %p sibling of parent\n", newLeftNode.get()); + if (gNoisy) {DebugDumpContent(); } // DEBUG } - } - // else we've found the style tag (referred to by "parent") - // nwMiddleNode is the node that is an ancestor to the selection - else - { - printf("* this is the style node\n"); - PRInt32 offsetInParent; - result = nsIEditorSupport::GetChildOffset(newMiddleNode, parent, offsetInParent); if (NS_SUCCEEDED(result)) { nsCOMPtrchildNodes; @@ -1488,40 +1464,78 @@ NS_IMETHODIMP nsTextEditor::RemoveTextPropertiesForNode(nsIDOMNode *aNode, if (NS_SUCCEEDED(result) && childNodes) { childNodes->GetLength(&count); - if (0!=offsetInParent && ((PRInt32)count!=offsetInParent+1)) { - printf("* splitting parent %p at offset %d\n", parent, offsetInParent); - result = nsEditor::SplitNode(parent, offsetInParent, getter_AddRefs(newLeftNode)); - printf("* split created left node %p sibling of parent\n", newLeftNode.get()); + NS_ASSERTION(count>0, "bad child count in newly split node"); + if ((PRInt32)count!=1) + { + printf("* splitting parent %p at offset %d\n", parent, 1); + result = nsEditor::SplitNode(parent, 1, getter_AddRefs(newMiddleNode)); + printf("* split created middle node %p sibling of parent\n", newMiddleNode.get()); if (gNoisy) {DebugDumpContent(); } // DEBUG } - if (NS_SUCCEEDED(result)) - { // promote the selection to the grandparent - nsCOMPtrgrandParent; - result = parent->GetParentNode(getter_AddRefs(grandParent)); - if (NS_SUCCEEDED(result) && grandParent) + else { + printf("* no need to split parent, newMiddleNode=parent\n"); + newMiddleNode = do_QueryInterface(parent); + } + NS_ASSERTION(newMiddleNode, "no middle node created"); + parent->GetParentNode(getter_AddRefs(temp)); + parent = do_QueryInterface(temp); + } + } + } + } + // else we've found the style tag (referred to by "parent") + // nwMiddleNode is the node that is an ancestor to the selection + else + { + printf("* this is the style node\n"); + PRInt32 offsetInParent; + result = nsIEditorSupport::GetChildOffset(newMiddleNode, parent, offsetInParent); + if (NS_SUCCEEDED(result)) + { + nsCOMPtrchildNodes; + result = parent->GetChildNodes(getter_AddRefs(childNodes)); + if (NS_SUCCEEDED(result) && childNodes) + { + childNodes->GetLength(&count); + if (0!=offsetInParent && ((PRInt32)count!=offsetInParent+1)) { + printf("* splitting parent %p at offset %d\n", parent, offsetInParent); + result = nsEditor::SplitNode(parent, offsetInParent, getter_AddRefs(newLeftNode)); + printf("* split created left node %p sibling of parent\n", newLeftNode.get()); + if (gNoisy) {DebugDumpContent(); } // DEBUG + } + if (NS_SUCCEEDED(result)) + { // promote the selection to the grandparent + nsCOMPtrgrandParent; + result = parent->GetParentNode(getter_AddRefs(grandParent)); + if (NS_SUCCEEDED(result) && grandParent) + { + printf("* deleting middle node %p\n", newMiddleNode.get()); + result = nsEditor::DeleteNode(newMiddleNode); + if (gNoisy) {DebugDumpContent(); } // DEBUG + if (NS_SUCCEEDED(result)) { - printf("* deleting middle node %p\n", newMiddleNode.get()); - result = nsEditor::DeleteNode(newMiddleNode); - if (gNoisy) {DebugDumpContent(); } // DEBUG - if (NS_SUCCEEDED(result)) + PRInt32 position; + result = nsIEditorSupport::GetChildOffset(parent, grandParent, position); + if (NS_SUCCEEDED(result)) { - PRInt32 position; - result = nsIEditorSupport::GetChildOffset(parent, grandParent, position); + if (PR_TRUE==insertAfter) + { + if (gNoisy) {printf("insertAfter=PR_TRUE, incr. position\n"); } + position++; + insertAfter = PR_FALSE; + } + printf("* inserting node %p in grandparent %p at offset %d\n", + newMiddleNode.get(), grandParent.get(), position); + result = nsEditor::InsertNode(newMiddleNode, grandParent, position); + if (gNoisy) {DebugDumpContent(); } // DEBUG if (NS_SUCCEEDED(result)) { - printf("* inserting node %p in grandparent %p at offset %d\n", - newMiddleNode.get(), grandParent.get(), position); - result = nsEditor::InsertNode(newMiddleNode, grandParent, position); - if (gNoisy) {DebugDumpContent(); } // DEBUG - if (NS_SUCCEEDED(result)) - { - PRBool hasChildren=PR_TRUE; - parent->HasChildNodes(&hasChildren); - if (PR_FALSE==hasChildren) { - printf("* deleting empty style node %p\n", parent.get()); - result = nsEditor::DeleteNode(parent); - if (gNoisy) {DebugDumpContent(); } // DEBUG - } + PRBool hasChildren=PR_TRUE; + parent->HasChildNodes(&hasChildren); + if (PR_FALSE==hasChildren) { + printf("* deleting empty style node %p\n", parent.get()); + result = nsEditor::DeleteNode(parent); + if (gNoisy) {DebugDumpContent(); } // DEBUG } } } @@ -1529,8 +1543,8 @@ NS_IMETHODIMP nsTextEditor::RemoveTextPropertiesForNode(nsIDOMNode *aNode, } } } - break; } + break; } } } @@ -1549,93 +1563,76 @@ nsTextEditor::RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, nsIDOMNode *aParent, nsIAtom *aPropName) { - printf("not yet implemented\n"); - return NS_OK; nsresult result=NS_OK; - PRBool textPropertySet; - IsTextPropertySetByContent(aStartNode, aPropName, textPropertySet); - if (PR_FALSE==textPropertySet) + PRInt32 startOffset = aStartOffset; + PRInt32 endOffset; + nsCOMPtrnodeAsChar; + nsCOMPtrparentNode = do_QueryInterface(aParent); + + // remove aPropName from all intermediate nodes + nsCOMPtrsiblingNode; + nsCOMPtrnextSiblingNode; // temp to hold the next node in the list + result = aStartNode->GetNextSibling(getter_AddRefs(siblingNode)); + while (siblingNode && NS_SUCCEEDED(result)) { - nsCOMPtrnewLeftTextNode; // this will be the middle text node - if (0!=aStartOffset) { - result = nsEditor::SplitNode(aStartNode, aStartOffset, getter_AddRefs(newLeftTextNode)); + // get next sibling right away, before we move siblingNode! + siblingNode->GetNextSibling(getter_AddRefs(nextSiblingNode)); + if (aEndNode==siblingNode.get()) { // found the end node, handle that below + break; } - if (NS_SUCCEEDED(result)) - { - nsCOMPtrendNodeAsChar; - endNodeAsChar = do_QueryInterface(aEndNode); - if (!endNodeAsChar) - return NS_ERROR_FAILURE; - PRUint32 count; - endNodeAsChar->GetLength(&count); - nsCOMPtrnewRightTextNode; // this will be the middle text node - if ((PRInt32)count!=aEndOffset) { - result = nsEditor::SplitNode(aEndNode, aEndOffset, getter_AddRefs(newRightTextNode)); + else + { // found a sibling node between aStartNode and aEndNode + PRUint32 childCount=0; + nodeAsChar = do_QueryInterface(siblingNode); + if (nodeAsChar) { + nodeAsChar->GetLength(&childCount); } - else { - newRightTextNode = do_QueryInterface(aEndNode); - } - if (NS_SUCCEEDED(result)) + else { - PRInt32 offsetInParent; - if (newLeftTextNode) { - result = nsIEditorSupport::GetChildOffset(newLeftTextNode, aParent, offsetInParent); + nsCOMPtrgrandChildNodes; + result = siblingNode->GetChildNodes(getter_AddRefs(grandChildNodes)); + if (NS_SUCCEEDED(result) && grandChildNodes) { + grandChildNodes->GetLength(&childCount); } - else { - offsetInParent = -1; // relies on +1 below in call to CreateNode - } - if (NS_SUCCEEDED(result)) - { - nsAutoString tag; - aPropName->ToString(tag); - // create the new style node, which will be the new parent for the selected nodes - nsCOMPtrnewStyleNode; - result = nsEditor::CreateNode(tag, aParent, offsetInParent+1, getter_AddRefs(newStyleNode)); - if (NS_SUCCEEDED(result)) - { // move the right half of the start node into the new style node - nsCOMPtrintermediateNode; - result = aStartNode->GetNextSibling(getter_AddRefs(intermediateNode)); - if (NS_SUCCEEDED(result)) - { - result = nsEditor::DeleteNode(aStartNode); - if (NS_SUCCEEDED(result)) - { - PRInt32 childIndex=0; - result = nsEditor::InsertNode(aStartNode, newStyleNode, childIndex); - childIndex++; - if (NS_SUCCEEDED(result)) - { // move all the intermediate nodes into the new style node - nsCOMPtrnextSibling; - while (intermediateNode.get() != aEndNode) - { - if (!intermediateNode) - result = NS_ERROR_NULL_POINTER; - if (NS_FAILED(result)) { - break; - } - // get the next sibling before moving the current child!!! - intermediateNode->GetNextSibling(getter_AddRefs(nextSibling)); - result = nsEditor::DeleteNode(intermediateNode); - if (NS_SUCCEEDED(result)) { - result = nsEditor::InsertNode(intermediateNode, newStyleNode, childIndex); - childIndex++; - } - intermediateNode = do_QueryInterface(nextSibling); - } - if (NS_SUCCEEDED(result)) - { // move the left half of the end node into the new style node - result = nsEditor::DeleteNode(newRightTextNode); - if (NS_SUCCEEDED(result)) - { - result = nsEditor::InsertNode(newRightTextNode, newStyleNode, childIndex); - } - } - } - } - } - } + if (0==childCount) + { // node has no children + // XXX: for now, I think that's ok. just pass in 0 } } + if (NS_SUCCEEDED(result)) { + siblingNode->GetParentNode(getter_AddRefs(parentNode)); + result = RemoveTextPropertiesForNode(siblingNode, parentNode, 0, childCount, aPropName); + } + } + siblingNode = do_QueryInterface(nextSiblingNode); + + } + if (NS_SUCCEEDED(result)) + { + // remove aPropName from aStartNode + nsCOMPtrnodeAsChar; + nodeAsChar = do_QueryInterface(aStartNode); + if (nodeAsChar) { + nodeAsChar->GetLength((PRUint32 *)&endOffset); + } + else + { + printf("not yet supported\n"); + return NS_ERROR_NOT_IMPLEMENTED; + } + result = aStartNode->GetParentNode(getter_AddRefs(parentNode)); + if (NS_SUCCEEDED(result)) { + result = RemoveTextPropertiesForNode(aStartNode, parentNode, startOffset, endOffset, aPropName); + } + } + if (NS_SUCCEEDED(result)) + { + // remove aPropName from the end node + startOffset = 0; + endOffset = aEndOffset; + result = aEndNode->GetParentNode(getter_AddRefs(parentNode)); + if (NS_SUCCEEDED(result)) { + result = RemoveTextPropertiesForNode(aEndNode, parentNode, startOffset, endOffset, aPropName); } } return result; diff --git a/mozilla/editor/libeditor/base/JoinElementTxn.cpp b/mozilla/editor/libeditor/base/JoinElementTxn.cpp index c12a638480f..4efa9caf8f6 100644 --- a/mozilla/editor/libeditor/base/JoinElementTxn.cpp +++ b/mozilla/editor/libeditor/base/JoinElementTxn.cpp @@ -90,7 +90,7 @@ NS_IMETHODIMP JoinElementTxn::Do(void) result = editor->JoinNodesImpl(mRightNode, mLeftNode, mParent, PR_FALSE); if (NS_SUCCEEDED(result)) { - if (gNoisy) { printf(" left node = %p removed\n", this, mLeftNode.get()); } + if (gNoisy) { printf(" left node = %p removed\n", mLeftNode.get()); } nsCOMPtrselection; mEditor->GetSelection(getter_AddRefs(selection)); if (selection) diff --git a/mozilla/editor/libeditor/text/nsTextEditRules.cpp b/mozilla/editor/libeditor/text/nsTextEditRules.cpp index 668c2a205a2..3266ac91bfd 100644 --- a/mozilla/editor/libeditor/text/nsTextEditRules.cpp +++ b/mozilla/editor/libeditor/text/nsTextEditRules.cpp @@ -286,7 +286,7 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta InsertStyleNode(newTextNode, nsIEditProperty::b, aSelection); } else { - printf("not yet implemented, make unbold in a bold context\n"); + printf("not yet implemented, make not bold in a bold context\n"); } } if (aTypeInState.IsSet(NS_TYPEINSTATE_ITALIC)) @@ -296,7 +296,7 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta } else { - printf("not yet implemented, make unitalic in a italic context\n"); + printf("not yet implemented, make not italic in a italic context\n"); } } if (aTypeInState.IsSet(NS_TYPEINSTATE_UNDERLINE)) @@ -334,21 +334,20 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta { // now we've got the body tag. insert the style tag if (aTypeInState.IsSet(NS_TYPEINSTATE_BOLD)) { - if (PR_TRUE==aTypeInState.GetBold()) - { // make the next char bold - nsAutoString tag; - nsIEditProperty::b->ToString(tag); - nsCOMPtrnewStyleNode; - nsCOMPtrnewTextNode; - result = mEditor->CreateNode(tag, bodyNode, 0, getter_AddRefs(newStyleNode)); - if (NS_SUCCEEDED(result)) - { - result = mEditor->CreateNode(nsIEditor::GetTextNodeTag(), newStyleNode, 0, getter_AddRefs(newTextNode)); - if (NS_SUCCEEDED(result)) - { - aSelection->Collapse(newTextNode, 0); - } - } + if (PR_TRUE==aTypeInState.GetBold()) { + InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::b, aSelection); + } + } + if (aTypeInState.IsSet(NS_TYPEINSTATE_ITALIC)) + { + if (PR_TRUE==aTypeInState.GetItalic()) { + InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::i, aSelection); + } + } + if (aTypeInState.IsSet(NS_TYPEINSTATE_UNDERLINE)) + { + if (PR_TRUE==aTypeInState.GetUnderline()) { + InsertStyleAndNewTextNode(bodyNode, nsIEditProperty::u, aSelection); } } } @@ -389,6 +388,50 @@ nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode, nsIAtom *aTag, nsIDOMSelecti } +NS_IMETHODIMP +nsTextEditRules::InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTag, nsIDOMSelection *aSelection) +{ + NS_ASSERTION(aParentNode && aTag, "bad args"); + if (!aParentNode || !aTag) { return NS_ERROR_NULL_POINTER; } + + nsresult result; + // if the selection already points to a text node, just call InsertStyleNode() + if (aSelection) + { + nsCOMPtranchor; + PRInt32 offset; + nsresult result = aSelection->GetAnchorNodeAndOffset(getter_AddRefs(anchor), &offset); + if ((NS_SUCCEEDED(result)) && anchor) + { + nsCOMPtranchorAsText; + anchorAsText = do_QueryInterface(anchor); + if (anchorAsText) + { + result = InsertStyleNode(anchor, aTag, aSelection); + return result; + } + } + } + // if we get here, there is no selected text node so we create one. + nsAutoString tag; + aTag->ToString(tag); + nsCOMPtrnewStyleNode; + nsCOMPtrnewTextNode; + result = mEditor->CreateNode(tag, aParentNode, 0, getter_AddRefs(newStyleNode)); + if (NS_SUCCEEDED(result)) + { + result = mEditor->CreateNode(nsIEditor::GetTextNodeTag(), newStyleNode, 0, getter_AddRefs(newTextNode)); + if (NS_SUCCEEDED(result)) + { + if (aSelection) { + aSelection->Collapse(newTextNode, 0); + } + } + } + return result; +} + + /* NS_IMETHODIMP nsTextEditRules::GetInsertBreakTag(nsIAtom **aTag) @@ -529,6 +572,7 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul nsCOMPtr parentNode; selectedNode->GetParentNode(getter_AddRefs(parentNode)); result = mEditor->JoinNodes(siblingNode, selectedNode, parentNode); + // selectedNode will remain after the join, siblingNode is removed } } selectedNode->GetNextSibling(getter_AddRefs(siblingNode)); @@ -543,8 +587,9 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul nsCOMPtr parentNode; selectedNode->GetParentNode(getter_AddRefs(parentNode)); result = mEditor->JoinNodes(selectedNode, siblingNode, parentNode); + // selectedNode will remain after the join, siblingNode is removed // set selection - aSelection->Collapse(selectedNode, selectedNodeLength); + aSelection->Collapse(siblingNode, selectedNodeLength); } } } diff --git a/mozilla/editor/libeditor/text/nsTextEditRules.h b/mozilla/editor/libeditor/text/nsTextEditRules.h index 18399280ea7..80a27f5647b 100644 --- a/mozilla/editor/libeditor/text/nsTextEditRules.h +++ b/mozilla/editor/libeditor/text/nsTextEditRules.h @@ -89,7 +89,19 @@ protected: * aSelection is optional. If provided, aSelection is set to (aNode, 0) * if aNode was successfully placed in a new style node */ - NS_IMETHOD InsertStyleNode(nsIDOMNode *aNode, nsIAtom *aTag, nsIDOMSelection *aSelection); + NS_IMETHOD InsertStyleNode(nsIDOMNode *aNode, + nsIAtom *aTag, + nsIDOMSelection *aSelection); + + /** create a new style node of type aTag in aParentNode, and put a new text node + * in the new style node. + * If aSelection is provided and points to a text node, just call InsertStyleNode instead. + * aSelection is optional. If provided, aSelection is set to (newTextNode, 0) + * if newTextNode was successfully created. + */ + NS_IMETHOD InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, + nsIAtom *aTag, + nsIDOMSelection *aSelection); // data nsTextEditor *mEditor; // note that we do not refcount the editor diff --git a/mozilla/editor/public/nsIEditor.h b/mozilla/editor/public/nsIEditor.h index 133370a2773..e5ac8f5c4e1 100644 --- a/mozilla/editor/public/nsIEditor.h +++ b/mozilla/editor/public/nsIEditor.h @@ -113,8 +113,8 @@ public: * @param aValue the value to set aAttribute to */ NS_IMETHOD SetAttribute(nsIDOMElement * aElement, - const nsString& aAttribute, - const nsString& aValue)=0; + const nsString& aAttribute, + const nsString& aValue)=0; /** * GetAttributeValue() retrieves the attribute's value for aElement. @@ -158,6 +158,8 @@ public: * @param aNode The DOM Node to insert. * @param aParent The node to insert the new object into * @param aPosition The place in aParent to insert the new node + * 0=first child, 1=second child, etc. + * any number > number of current children = last child */ NS_IMETHOD InsertNode(nsIDOMNode * aNode, nsIDOMNode * aParent, @@ -203,8 +205,8 @@ public: * @param aNewLeftNode [OUT] the new node resulting from the split, becomes aExistingRightNode's previous sibling. */ NS_IMETHOD SplitNode(nsIDOMNode * aExistingRightNode, - PRInt32 aOffset, - nsIDOMNode ** aNewLeftNode)=0; + PRInt32 aOffset, + nsIDOMNode ** aNewLeftNode)=0; /** * JoinNodes() takes 2 nodes and merge their content|children. diff --git a/mozilla/editor/txmgr/src/nsTransactionItem.cpp b/mozilla/editor/txmgr/src/nsTransactionItem.cpp index 88b745a70bf..791c257eb75 100644 --- a/mozilla/editor/txmgr/src/nsTransactionItem.cpp +++ b/mozilla/editor/txmgr/src/nsTransactionItem.cpp @@ -19,6 +19,10 @@ #include "nsTransactionItem.h" #include "nsCOMPtr.h" +#ifdef NS_DEBUG +//#define NOISY +#endif + nsTransactionItem::nsTransactionItem(nsITransaction *aTransaction) : mTransaction(aTransaction), mUndoStack(0), mRedoStack(0) { @@ -112,6 +116,12 @@ nsTransactionItem::Undo() if (!mTransaction) return NS_OK; +#ifdef NOISY + nsAutoString redoString; + mTransaction->GetRedoString(&redoString); + printf("undoing %s\n", redoString); +#endif + result = mTransaction->Undo(); if (NS_FAILED(result)) { @@ -149,6 +159,12 @@ nsTransactionItem::UndoChildren() return result; } +#ifdef NOISY + nsAutoString redoString; + item->GetRedoString(&redoString); + printf("undoing %s\n", redoString); +#endif + result = item->Undo(); if (NS_FAILED(result)) { @@ -181,6 +197,13 @@ nsTransactionItem::Redo() nsresult result; if (mTransaction) { + +#ifdef NOISY + nsAutoString undoString; + mTransaction->GetUndoString(&undoString); + printf("redoing %s\n", undoString); +#endif + result = mTransaction->Redo(); if (NS_FAILED(result)) @@ -221,6 +244,12 @@ nsTransactionItem::RedoChildren() return result; } +#ifdef NOISY + nsAutoString undoString; + item->GetUndoString(&undoString); + printf("redoing %s\n", undoString); +#endif + result = item->Redo(); if (NS_FAILED(result)) {