diff --git a/editor/base/Makefile.in b/editor/base/Makefile.in index e9928930ac9..31c12c00532 100644 --- a/editor/base/Makefile.in +++ b/editor/base/Makefile.in @@ -29,6 +29,7 @@ CPPSRCS = \ nsEditor.cpp \ nsTextEditor.cpp \ nsTextEditRules.cpp \ + TextEditorTest.cpp \ nsHTMLEditRules.cpp \ nsEditorEventListeners.cpp \ nsEditProperty.cpp \ diff --git a/editor/base/makefile.win b/editor/base/makefile.win index db0c236e20d..44b39bc1143 100644 --- a/editor/base/makefile.win +++ b/editor/base/makefile.win @@ -25,6 +25,7 @@ CPPSRCS = \ nsTextEditor.cpp \ nsTextEditRules.cpp \ nsHTMLEditRules.cpp \ + TextEditorTest.cpp \ nsEditorEventListeners.cpp \ nsEditProperty.cpp \ nsEditFactory.cpp \ @@ -60,6 +61,7 @@ CPP_OBJS = \ .\$(OBJDIR)\nsEditor.obj \ .\$(OBJDIR)\nsTextEditor.obj \ .\$(OBJDIR)\nsTextEditRules.obj \ + .\$(OBJDIR)\TextEditorTest.obj \ .\$(OBJDIR)\nsHTMLEditRules.obj \ .\$(OBJDIR)\nsEditorEventListeners.obj \ .\$(OBJDIR)\nsEditProperty.obj \ diff --git a/editor/base/nsEditProperty.cpp b/editor/base/nsEditProperty.cpp index 5690a29a010..cb5d034fe55 100644 --- a/editor/base/nsEditProperty.cpp +++ b/editor/base/nsEditProperty.cpp @@ -17,6 +17,7 @@ */ #include "nsEditProperty.h" +#include "nsString.h" static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kIEditPropertyIID, NS_IEDITPROPERTY_IID); @@ -40,6 +41,7 @@ nsIAtom * nsIEditProperty::sub; nsIAtom * nsIEditProperty::sup; nsIAtom * nsIEditProperty::tt; nsIAtom * nsIEditProperty::u; +nsString * nsIEditProperty::allProperties; void nsEditProperty::InstanceInit() @@ -57,6 +59,7 @@ nsEditProperty::InstanceInit() nsIEditProperty::sup = NS_NewAtom("SUP"); nsIEditProperty::tt = NS_NewAtom("TT"); nsIEditProperty::u = NS_NewAtom("U"); + nsIEditProperty::allProperties = new nsString("moz_AllProperties"); } void @@ -75,6 +78,9 @@ nsEditProperty::InstanceShutdown() NS_IF_RELEASE(nsIEditProperty::sup); NS_IF_RELEASE(nsIEditProperty::tt); NS_IF_RELEASE(nsIEditProperty::u); + if (nsIEditProperty::allProperties) { + delete (nsIEditProperty::allProperties); + } } NS_IMETHODIMP diff --git a/editor/base/nsEditor.cpp b/editor/base/nsEditor.cpp index 8be8a419bb9..2228b617114 100644 --- a/editor/base/nsEditor.cpp +++ b/editor/base/nsEditor.cpp @@ -147,7 +147,7 @@ static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID); #define NS_ERROR_EDITOR_NO_TEXTNODE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,2) #ifdef NS_DEBUG_EDITOR -static PRBool gNoisy = PR_TRUE; +static PRBool gNoisy = PR_FALSE; #else static const PRBool gNoisy = PR_FALSE; #endif @@ -1848,7 +1848,7 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode, nsIDOMNode* aParent) { -printf("SplitNodeImpl: left=%p, right=%p, offset=%d\n", aNewLeftNode, aExistingRightNode, aOffset); + if (gNoisy) { printf("SplitNodeImpl: left=%p, right=%p, offset=%d\n", aNewLeftNode, aExistingRightNode, aOffset); } nsresult result; NS_ASSERTION(((nsnull!=aExistingRightNode) && diff --git a/editor/base/nsEditorEventListeners.cpp b/editor/base/nsEditorEventListeners.cpp index 98d67d01576..eb42d0ce72c 100644 --- a/editor/base/nsEditorEventListeners.cpp +++ b/editor/base/nsEditorEventListeners.cpp @@ -28,6 +28,12 @@ #include "nsString.h" #include "nsIStringStream.h" +#ifdef NS_DEBUG +#ifdef EDITOR_SELFTEST +#include "TextEditorTest.h" +#endif +#endif + static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID); static NS_DEFINE_IID(kIDOMCharacterDataIID, NS_IDOMCHARACTERDATA_IID); @@ -338,12 +344,12 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr PRBool any = PR_FALSE; PRBool all = PR_FALSE; PRBool first = PR_FALSE; - mEditor->GetTextProperty(nsIEditProperty::i, first, any, all); + mEditor->GetTextProperty(nsIEditProperty::i, nsnull, nsnull, first, any, all); if (PR_FALSE==first) { - mEditor->SetTextProperty(nsIEditProperty::i); + mEditor->SetTextProperty(nsIEditProperty::i, nsnull, nsnull); } else { - mEditor->RemoveTextProperty(nsIEditProperty::i); + mEditor->RemoveTextProperty(nsIEditProperty::i, nsnull); } } } @@ -375,12 +381,12 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr PRBool any = PR_FALSE; PRBool all = PR_FALSE; PRBool first = PR_FALSE; - mEditor->GetTextProperty(nsIEditProperty::b, first, any, all); + mEditor->GetTextProperty(nsIEditProperty::b, nsnull, nsnull, first, any, all); if (PR_FALSE==first) { - mEditor->SetTextProperty(nsIEditProperty::b); + mEditor->SetTextProperty(nsIEditProperty::b, nsnull, nsnull); } else { - mEditor->RemoveTextProperty(nsIEditProperty::b); + mEditor->RemoveTextProperty(nsIEditProperty::b, nsnull); } } } @@ -398,17 +404,76 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr PRBool any = PR_FALSE; PRBool all = PR_FALSE; PRBool first = PR_FALSE; - mEditor->GetTextProperty(nsIEditProperty::u, first, any, all); + mEditor->GetTextProperty(nsIEditProperty::u, nsnull, nsnull, first, any, all); if (PR_FALSE==first) { - mEditor->SetTextProperty(nsIEditProperty::u); + mEditor->SetTextProperty(nsIEditProperty::u, nsnull, nsnull); } else { - mEditor->RemoveTextProperty(nsIEditProperty::u); + mEditor->RemoveTextProperty(nsIEditProperty::u, nsnull); } } } break; + + // hard-coded ChangeTextAttributes test -- font color red + case nsIDOMEvent::VK_1: + if (PR_TRUE==ctrlKey) + { + aProcessed=PR_TRUE; + if (mEditor) + { + // XXX: move this logic down into texteditor rules delegate + // should just call mEditor->ChangeTextProperty(prop) + PRBool any = PR_FALSE; + PRBool all = PR_FALSE; + PRBool first = PR_FALSE; + nsAutoString color = "color"; + nsAutoString value = "red"; + mEditor->SetTextProperty(nsIEditProperty::font, &color, &value); + } + } + break; + + // hard-coded ChangeTextAttributes test -- font color green + case nsIDOMEvent::VK_2: + if (PR_TRUE==ctrlKey) + { + aProcessed=PR_TRUE; + if (mEditor) + { + // XXX: move this logic down into texteditor rules delegate + // should just call mEditor->ChangeTextProperty(prop) + PRBool any = PR_FALSE; + PRBool all = PR_FALSE; + PRBool first = PR_FALSE; + nsAutoString color = "color"; + nsAutoString value = "green"; + mEditor->SetTextProperty(nsIEditProperty::font, &color, &value); + } + } + break; + +#ifdef NS_DEBUG +#ifdef EDITOR_SELFTEST + // hard-coded Text Editor Unit Test + case nsIDOMEvent::VK_T: + if (PR_TRUE==ctrlKey) + { + aProcessed=PR_TRUE; + if (mEditor) + { + TextEditorTest *tester = new TextEditorTest(); + if (tester) + { + tester->Run(mEditor); + } + } + } + break; +#endif +#endif + } } return NS_OK; diff --git a/editor/base/nsHTMLEditor.cpp b/editor/base/nsHTMLEditor.cpp index 29bb4ca8135..de908312185 100644 --- a/editor/base/nsHTMLEditor.cpp +++ b/editor/base/nsHTMLEditor.cpp @@ -109,19 +109,24 @@ void nsHTMLEditor::InitRules() mRules->Init(this); } -NS_IMETHODIMP nsHTMLEditor::SetTextProperty(nsIAtom *aProperty) +NS_IMETHODIMP nsHTMLEditor::SetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue) { - return nsTextEditor::SetTextProperty(aProperty); + return nsTextEditor::SetTextProperty(aProperty, aAttribute, aValue); } -NS_IMETHODIMP nsHTMLEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll) +NS_IMETHODIMP nsHTMLEditor::GetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue, + PRBool &aFirst, PRBool &aAny, PRBool &aAll) { - return nsTextEditor::GetTextProperty(aProperty, aFirst, aAny, aAll); + return nsTextEditor::GetTextProperty(aProperty, aAttribute, aValue, aFirst, aAny, aAll); } -NS_IMETHODIMP nsHTMLEditor::RemoveTextProperty(nsIAtom *aProperty) +NS_IMETHODIMP nsHTMLEditor::RemoveTextProperty(nsIAtom *aProperty, const nsString *aAttribute) { - return nsTextEditor::RemoveTextProperty(aProperty); + return nsTextEditor::RemoveTextProperty(aProperty, aAttribute); } NS_IMETHODIMP nsHTMLEditor::DeleteSelection(nsIEditor::Direction aDir) diff --git a/editor/base/nsHTMLEditor.h b/editor/base/nsHTMLEditor.h index f2d9d111281..b7cc9424622 100644 --- a/editor/base/nsHTMLEditor.h +++ b/editor/base/nsHTMLEditor.h @@ -50,9 +50,13 @@ public: // Methods that are duplicates of nsTextEditor -- exposed here for convenience // Editing Operations - NS_IMETHOD SetTextProperty(nsIAtom *aProperty); - NS_IMETHOD GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll); - NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty); + NS_IMETHOD SetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue); + NS_IMETHOD GetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, const nsString *aValue, + PRBool &aFirst, PRBool &aAny, PRBool &aAll); + NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty, const nsString *aAttribute); NS_IMETHOD DeleteSelection(nsIEditor::Direction aDir); NS_IMETHOD InsertText(const nsString& aStringToInsert); NS_IMETHOD InsertBreak(); diff --git a/editor/base/nsIEditProperty.h b/editor/base/nsIEditProperty.h index e7180bd7af7..502a26a4f89 100644 --- a/editor/base/nsIEditProperty.h +++ b/editor/base/nsIEditProperty.h @@ -22,6 +22,7 @@ #include "nsISupports.h" class nsIAtom; +class nsString; #define NS_IEDITPROPERTY_IID \ {/* 9875cd40-ca81-11d2-8f4d-006008159b0c*/ \ @@ -70,6 +71,9 @@ SUB places text in subscript style SUP places text in superscript style */ + /** special strings */ + static nsString *allProperties; // this magic string represents the union of all inline style tags + // XXX: end temp code }; diff --git a/editor/base/nsTextEditor.cpp b/editor/base/nsTextEditor.cpp index 4c6c7d60828..3f814fcd274 100644 --- a/editor/base/nsTextEditor.cpp +++ b/editor/base/nsTextEditor.cpp @@ -305,7 +305,9 @@ void nsTextEditor::InitRules() } -NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty) +NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue) { if (!aProperty) return NS_ERROR_NULL_POINTER; @@ -329,10 +331,20 @@ NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty) if (PR_TRUE==isCollapsed) { // manipulating text attributes on a collapsed selection only sets state for the next text insertion - SetTypeInStateForProperty(mTypeInState, aProperty); + SetTypeInStateForProperty(mTypeInState, aProperty, aAttribute); } else { + // remember start and end points of selection + // XXX: this won't work for discontiguous selections + nsCOMPtr selStartNode; + PRInt32 selStartOffset; + nsCOMPtr selEndNode; + PRInt32 selEndOffset; + selection->GetAnchorNodeAndOffset(getter_AddRefs(selStartNode), &selStartOffset); + selection->GetFocusNodeAndOffset(getter_AddRefs(selEndNode), &selEndOffset); + + // set the text property for all selected ranges nsEditor::BeginTransaction(); nsCOMPtr enumerator; enumerator = do_QueryInterface(selection); @@ -360,7 +372,7 @@ NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty) startParent->GetParentNode(getter_AddRefs(commonParent)); result = SetTextPropertiesForNode(startParent, commonParent, startOffset, endOffset, - aProperty); + aProperty, aAttribute, aValue); } else { @@ -385,7 +397,7 @@ NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty) result = SetTextPropertiesForNodesWithSameParent(startParent,startOffset, endParent, endOffset, commonParent, - aProperty); + aProperty, aAttribute, aValue); } else { // the range is between 2 nodes that have no simple relationship @@ -393,7 +405,7 @@ NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty) startParent,startOffset, endParent, endOffset, commonParent, - aProperty); + aProperty, aAttribute, aValue); } } } @@ -420,7 +432,10 @@ NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty) return result; } -NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll) +NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue, + PRBool &aFirst, PRBool &aAny, PRBool &aAll) { if (!aProperty) return NS_ERROR_NULL_POINTER; @@ -497,7 +512,7 @@ NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, { PRBool isSet; nsCOMPtrresultNode; - IsTextPropertySetByContent(node, aProperty, isSet, getter_AddRefs(resultNode)); + IsTextPropertySetByContent(node, aProperty, aAttribute, aValue, isSet, getter_AddRefs(resultNode)); if (PR_TRUE==first) { aFirst = isSet; @@ -513,7 +528,7 @@ NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, } } iter->Next(); - result = iter->CurrentNode(getter_AddRefs(content)); + iter->CurrentNode(getter_AddRefs(content)); } } } @@ -525,6 +540,7 @@ NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, void nsTextEditor::IsTextStyleSet(nsIStyleContext *aSC, nsIAtom *aProperty, + const nsString *aAttribute, PRBool &aIsSet) const { aIsSet = PR_FALSE; @@ -542,13 +558,17 @@ void nsTextEditor::IsTextStyleSet(nsIStyleContext *aSC, } } -void nsTextEditor::IsTextPropertySetByContent(nsIDOMNode *aNode, - nsIAtom *aProperty, - PRBool &aIsSet, - nsIDOMNode **aStyleNode) const +// this will NOT find aAttribute unless aAttribute has a non-null value +// so singleton attributes like will not be matched! +void nsTextEditor::IsTextPropertySetByContent(nsIDOMNode *aNode, + nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue, + PRBool &aIsSet, + nsIDOMNode **aStyleNode) const { nsresult result; - aIsSet = PR_FALSE; + aIsSet = PR_FALSE; // must be initialized to false for code below to work nsAutoString propName; aProperty->ToString(propName); nsCOMPtrparent; @@ -563,8 +583,32 @@ void nsTextEditor::IsTextPropertySetByContent(nsIDOMNode *aNode, element->GetTagName(tag); if (propName.Equals(tag)) { - aIsSet = PR_TRUE; - break; + PRBool found = PR_FALSE; + if (aAttribute) + { + nsAutoString value; + element->GetAttribute(*aAttribute, value); + if (0!=value.Length()) + { + if (!aValue) { + found = PR_TRUE; + } + else if (aValue->Equals(value)) { + found = PR_TRUE; + } + else { // we found the prop with the attribute, but the value doesn't match + break; + } + } + } + else { + found = PR_TRUE; + } + if (PR_TRUE==found) + { + aIsSet = PR_TRUE; + break; + } } } nsCOMPtrtemp; @@ -579,7 +623,7 @@ void nsTextEditor::IsTextPropertySetByContent(nsIDOMNode *aNode, } -NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty) +NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty, const nsString *aAttribute) { if (!aProperty) return NS_ERROR_NULL_POINTER; @@ -603,11 +647,13 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty) if (PR_TRUE==isCollapsed) { // manipulating text attributes on a collapsed selection only sets state for the next text insertion - SetTypeInStateForProperty(mTypeInState, aProperty); + SetTypeInStateForProperty(mTypeInState, aProperty, aAttribute); } else { nsEditor::BeginTransaction(); + nsCOMPtr startParent, endParent; + PRInt32 startOffset, endOffset; nsCOMPtr enumerator; enumerator = do_QueryInterface(selection); if (enumerator) @@ -622,10 +668,8 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty) result = range->GetCommonParent(getter_AddRefs(commonParent)); if ((NS_SUCCEEDED(result)) && commonParent) { - PRInt32 startOffset, endOffset; range->GetStartOffset(&startOffset); range->GetEndOffset(&endOffset); - nsCOMPtr startParent; nsCOMPtr endParent; range->GetStartParent(getter_AddRefs(startParent)); range->GetEndParent(getter_AddRefs(endParent)); if (startParent.get()==endParent.get()) @@ -634,7 +678,7 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty) startParent->GetParentNode(getter_AddRefs(commonParent)); result = RemoveTextPropertiesForNode(startParent, commonParent, startOffset, endOffset, - aProperty); + aProperty, nsnull); } else { @@ -659,7 +703,7 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty) result = RemoveTextPropertiesForNodesWithSameParent(startParent,startOffset, endParent, endOffset, commonParent, - aProperty); + aProperty, nsnull); } else { // the range is between 2 nodes that have no simple relationship @@ -667,7 +711,7 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty) startParent,startOffset, endParent, endOffset, commonParent, - aProperty); + aProperty, nsnull); } } } @@ -684,10 +728,11 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty) } } nsEditor::EndTransaction(); - } - if (NS_SUCCEEDED(result)) - { // set the selection - // XXX: can't do anything until I can create ranges + if (NS_SUCCEEDED(result)) + { + selection->Collapse(startParent, startOffset); + selection->Extend(endParent, endOffset); + } } } return result; @@ -1065,11 +1110,13 @@ NS_IMETHODIMP nsTextEditor::OutputHTML(nsString& aOutputString) } -NS_IMETHODIMP nsTextEditor::SetTextPropertiesForNode(nsIDOMNode *aNode, - nsIDOMNode *aParent, - PRInt32 aStartOffset, - PRInt32 aEndOffset, - nsIAtom *aPropName) +NS_IMETHODIMP nsTextEditor::SetTextPropertiesForNode(nsIDOMNode *aNode, + nsIDOMNode *aParent, + PRInt32 aStartOffset, + PRInt32 aEndOffset, + nsIAtom *aPropName, + const nsString *aAttribute, + const nsString *aValue) { if (gNoisy) { printf("nsTextEditor::SetTextPropertyForNode\n"); } nsresult result=NS_OK; @@ -1080,50 +1127,95 @@ NS_IMETHODIMP nsTextEditor::SetTextPropertiesForNode(nsIDOMNode *aNode, PRBool textPropertySet; nsCOMPtrresultNode; - IsTextPropertySetByContent(aNode, aPropName, textPropertySet, getter_AddRefs(resultNode)); + IsTextPropertySetByContent(aNode, aPropName, aAttribute, aValue, textPropertySet, getter_AddRefs(resultNode)); if (PR_FALSE==textPropertySet) { PRUint32 count; nodeAsChar->GetLength(&count); nsCOMPtrnewTextNode; // this will be the text node we move into the new style node + // split the node at the start offset unless the split would create an empty node if (aStartOffset!=0) { result = nsEditor::SplitNode(aNode, aStartOffset, getter_AddRefs(newTextNode)); + if (gNoisy) { printf("* split created left node %p\n", newTextNode.get());} + if (gNoisy) {DebugDumpContent(); } // DEBUG } if (NS_SUCCEEDED(result)) { if (aEndOffset!=(PRInt32)count) { result = nsEditor::SplitNode(aNode, aEndOffset-aStartOffset, getter_AddRefs(newTextNode)); + if (gNoisy) { printf("* split created left node %p\n", newTextNode.get());} + if (gNoisy) {DebugDumpContent(); } // DEBUG } else { newTextNode = do_QueryInterface(aNode); + if (gNoisy) { printf("* second split not required, new text node set to aNode = %p\n", newTextNode.get());} } if (NS_SUCCEEDED(result)) { - nsAutoString tag; - aPropName->ToString(tag); - PRInt32 offsetInParent; - result = nsIEditorSupport::GetChildOffset(aNode, aParent, offsetInParent); - if (NS_SUCCEEDED(result)) + // optimization: if all we're doing is changing a value for an existing attribute for the + // entire selection, then just twiddle the existing style node + PRBool done = PR_FALSE; // set to true in optimized case if we can really do the optimization + if (aAttribute && aValue && (0==aStartOffset) && (aEndOffset==(PRInt32)count)) { - nsCOMPtrnewStyleNode; - result = nsEditor::CreateNode(tag, aParent, offsetInParent, getter_AddRefs(newStyleNode)); - if (NS_SUCCEEDED(result)) + // ??? can we really compute this? + } + if (PR_FALSE==done) + { + nsCOMPtrnewTextNodeAsChar; + newTextNodeAsChar = do_QueryInterface(newTextNode); + PRUint32 newTextNodeLength; + newTextNodeAsChar->GetLength(&newTextNodeLength); + if (0==newTextNodeLength) { - result = nsEditor::DeleteNode(newTextNode); - if (NS_SUCCEEDED(result)) { - result = nsEditor::InsertNode(newTextNode, newStyleNode, 0); - if (NS_SUCCEEDED(result)) - { // set the selection - nsCOMPtrselection; - result = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_SUCCEEDED(result)) { - selection->Collapse(newTextNode, 0); - PRInt32 endOffset = aEndOffset-aStartOffset; - selection->Extend(newTextNode, endOffset); + result = nsEditor::DeleteNode(newTextNode); + } + else + { + nsAutoString tag; + aPropName->ToString(tag); + PRInt32 offsetInParent; + result = nsIEditorSupport::GetChildOffset(aNode, aParent, offsetInParent); + if (NS_SUCCEEDED(result)) + { + nsCOMPtrnewStyleNode; + result = nsEditor::CreateNode(tag, aParent, offsetInParent, getter_AddRefs(newStyleNode)); + if (NS_SUCCEEDED(result) && newStyleNode) + { + if (gNoisy) { printf("* created new style node %p\n", newStyleNode.get());} + if (gNoisy) {DebugDumpContent(); } // DEBUG + if (aAttribute) + { + nsCOMPtr newStyleElement; + newStyleElement = do_QueryInterface(newStyleNode); + nsAutoString value; + if (aValue) { + value = *aValue; + } + // XXX should be a call to editor to change attribute! + result = newStyleElement->SetAttribute(*aAttribute, value); + } + if (NS_SUCCEEDED(result)) + { + result = nsEditor::DeleteNode(newTextNode); + if (NS_SUCCEEDED(result)) + { + result = nsEditor::InsertNode(newTextNode, newStyleNode, 0); + if (NS_SUCCEEDED(result)) + { // set the selection + nsCOMPtrselection; + result = nsEditor::GetSelection(getter_AddRefs(selection)); + if (NS_SUCCEEDED(result)) + { + selection->Collapse(newTextNode, 0); + PRInt32 endOffset = aEndOffset-aStartOffset; + selection->Extend(newTextNode, endOffset); + } + } + } } } } @@ -1237,18 +1329,20 @@ nsTextEditor::IntermediateNodesAreInline(nsIDOMRange *aRange, /* this should only get called if the only intervening nodes are inline style nodes */ NS_IMETHODIMP -nsTextEditor::SetTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, - PRInt32 aStartOffset, - nsIDOMNode *aEndNode, - PRInt32 aEndOffset, - nsIDOMNode *aParent, - nsIAtom *aPropName) +nsTextEditor::SetTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, + PRInt32 aStartOffset, + nsIDOMNode *aEndNode, + PRInt32 aEndOffset, + nsIDOMNode *aParent, + nsIAtom *aPropName, + const nsString *aAttribute, + const nsString *aValue) { if (gNoisy) { printf("nsTextEditor::SetTextPropertiesForNodesWithSameParent\n"); } nsresult result=NS_OK; PRBool textPropertySet; nsCOMPtrresultNode; - IsTextPropertySetByContent(aStartNode, aPropName, textPropertySet, getter_AddRefs(resultNode)); + IsTextPropertySetByContent(aStartNode, aPropName, aAttribute, aValue, textPropertySet, getter_AddRefs(resultNode)); if (PR_FALSE==textPropertySet) { nsCOMPtrnewLeftTextNode; // this will be the middle text node @@ -1350,7 +1444,9 @@ nsTextEditor::SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange, nsIDOMNode *aEndNode, PRInt32 aEndOffset, nsIDOMNode *aParent, - nsIAtom *aPropName) + nsIAtom *aPropName, + const nsString *aAttribute, + const nsString *aValue) { if (gNoisy) { printf("nsTextEditor::SetTextPropertiesForNodeWithDifferentParents\n"); } nsresult result=NS_OK; @@ -1394,7 +1490,7 @@ nsTextEditor::SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange, node = do_QueryInterface(content); PRBool textPropertySet; nsCOMPtrresultNode; - IsTextPropertySetByContent(node, aPropName, textPropertySet, getter_AddRefs(resultNode)); + IsTextPropertySetByContent(node, aPropName, aAttribute, aValue, textPropertySet, getter_AddRefs(resultNode)); if (PR_FALSE==textPropertySet) { nsCOMPtrparent; @@ -1435,7 +1531,7 @@ nsTextEditor::SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange, return NS_ERROR_FAILURE; PRUint32 count; nodeAsChar->GetLength(&count); - result = SetTextPropertiesForNode(aStartNode, parent, aStartOffset, count, aPropName); + result = SetTextPropertiesForNode(aStartNode, parent, aStartOffset, count, aPropName, aAttribute, aValue); // create a style node for the text in the end parent result = aEndNode->GetParentNode(getter_AddRefs(parent)); @@ -1446,7 +1542,7 @@ nsTextEditor::SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange, if (!nodeAsChar) return NS_ERROR_FAILURE; nodeAsChar->GetLength(&count); - result = SetTextPropertiesForNode(aEndNode, parent, 0, aEndOffset, aPropName); + result = SetTextPropertiesForNode(aEndNode, parent, 0, aEndOffset, aPropName, aAttribute, aValue); return result; } @@ -1455,7 +1551,8 @@ NS_IMETHODIMP nsTextEditor::RemoveTextPropertiesForNode(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aStartOffset, PRInt32 aEndOffset, - nsIAtom *aPropName) + nsIAtom *aPropName, + const nsString *aAttribute) { if (gNoisy) { printf("nsTextEditor::RemoveTextPropertyForNode\n"); } nsresult result=NS_OK; @@ -1463,7 +1560,7 @@ NS_IMETHODIMP nsTextEditor::RemoveTextPropertiesForNode(nsIDOMNode *aNode, nodeAsChar = do_QueryInterface(aNode); PRBool textPropertySet; nsCOMPtrresultNode; - IsTextPropertySetByContent(aNode, aPropName, textPropertySet, getter_AddRefs(resultNode)); + IsTextPropertySetByContent(aNode, aPropName, aAttribute, nsnull, textPropertySet, getter_AddRefs(resultNode)); if (PR_TRUE==textPropertySet) { nsCOMPtrparent; // initially set to first interior parent node to process @@ -1670,7 +1767,8 @@ nsTextEditor::RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, nsIDOMNode *aEndNode, PRInt32 aEndOffset, nsIDOMNode *aParent, - nsIAtom *aPropName) + nsIAtom *aPropName, + const nsString *aAttribute) { if (gNoisy) { printf("nsTextEditor::RemoveTextPropertiesForNodesWithSameParent\n"); } nsresult result=NS_OK; @@ -1711,7 +1809,7 @@ nsTextEditor::RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, } if (NS_SUCCEEDED(result)) { siblingNode->GetParentNode(getter_AddRefs(parentNode)); - result = RemoveTextPropertiesForNode(siblingNode, parentNode, 0, childCount, aPropName); + result = RemoveTextPropertiesForNode(siblingNode, parentNode, 0, childCount, aPropName, aAttribute); } } siblingNode = do_QueryInterface(nextSiblingNode); @@ -1731,7 +1829,7 @@ nsTextEditor::RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, } result = aStartNode->GetParentNode(getter_AddRefs(parentNode)); if (NS_SUCCEEDED(result)) { - result = RemoveTextPropertiesForNode(aStartNode, parentNode, startOffset, endOffset, aPropName); + result = RemoveTextPropertiesForNode(aStartNode, parentNode, startOffset, endOffset, aPropName, aAttribute); } } if (NS_SUCCEEDED(result)) @@ -1741,7 +1839,7 @@ nsTextEditor::RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, endOffset = aEndOffset; result = aEndNode->GetParentNode(getter_AddRefs(parentNode)); if (NS_SUCCEEDED(result)) { - result = RemoveTextPropertiesForNode(aEndNode, parentNode, startOffset, endOffset, aPropName); + result = RemoveTextPropertiesForNode(aEndNode, parentNode, startOffset, endOffset, aPropName, aAttribute); } } return result; @@ -1754,7 +1852,8 @@ nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRang nsIDOMNode *aEndNode, PRInt32 aEndOffset, nsIDOMNode *aParent, - nsIAtom *aPropName) + nsIAtom *aPropName, + const nsString *aAttribute) { if (gNoisy) { printf("nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents\n"); } nsresult result=NS_OK; @@ -1776,8 +1875,8 @@ nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRang nodeAsChar = do_QueryInterface(aStartNode); if (!nodeAsChar) { return NS_ERROR_FAILURE; } nodeAsChar->GetLength(&count); - if (aStartOffset!=count) { // only do this if at least one child is selected - result = RemoveTextPropertiesForNode(aStartNode, parent, aStartOffset, count, aPropName); + if ((PRUint32)aStartOffset!=count) { // only do this if at least one child is selected + result = RemoveTextPropertiesForNode(aStartNode, parent, aStartOffset, count, aPropName, aAttribute); if (0!=aStartOffset) { rangeStartOffset = 0; // we split aStartNode at aStartOffset and it is the right node now } @@ -1798,7 +1897,7 @@ nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRang if (!nodeAsChar) { return NS_ERROR_FAILURE; } nodeAsChar->GetLength(&count); if (aEndOffset!=0) { // only do this if at least one child is selected - result = RemoveTextPropertiesForNode(aEndNode, parent, 0, aEndOffset, aPropName); + result = RemoveTextPropertiesForNode(aEndNode, parent, 0, aEndOffset, aPropName, aAttribute); if (0!=aEndOffset) { rangeEndOffset = 0; // we split aEndNode at aEndOffset and it is the right node now } @@ -1934,7 +2033,9 @@ nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRang } NS_IMETHODIMP -nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState, nsIAtom *aPropName) +nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState, + nsIAtom *aPropName, + const nsString *aAttribute) { if (!aPropName) { return NS_ERROR_NULL_POINTER; @@ -1950,7 +2051,7 @@ nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState, nsIAtom *aPro PRBool any = PR_FALSE; PRBool all = PR_FALSE; PRBool first = PR_FALSE; - GetTextProperty(aPropName, first, any, all); // operates on current selection + GetTextProperty(aPropName, aAttribute, nsnull, first, any, all); // operates on current selection aTypeInState.SetBold(!any); } } @@ -1965,7 +2066,7 @@ nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState, nsIAtom *aPro PRBool any = PR_FALSE; PRBool all = PR_FALSE; PRBool first = PR_FALSE; - GetTextProperty(aPropName, first, any, all); // operates on current selection + GetTextProperty(aPropName, aAttribute, nsnull, first, any, all); // operates on current selection aTypeInState.SetItalic(!any); } } @@ -1980,7 +2081,7 @@ nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState, nsIAtom *aPro PRBool any = PR_FALSE; PRBool all = PR_FALSE; PRBool first = PR_FALSE; - GetTextProperty(aPropName, first, any, all); // operates on current selection + GetTextProperty(aPropName, aAttribute, nsnull, first, any, all); // operates on current selection aTypeInState.SetUnderline(!any); } } diff --git a/editor/base/nsTextEditor.h b/editor/base/nsTextEditor.h index 603305ba1ed..e43267672c0 100644 --- a/editor/base/nsTextEditor.h +++ b/editor/base/nsTextEditor.h @@ -51,9 +51,14 @@ public: NS_IMETHOD Init(nsIDOMDocument *aDoc, nsIPresShell *aPresShell); // Editing Operations - NS_IMETHOD SetTextProperty(nsIAtom *aProperty); - NS_IMETHOD GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll); - NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty); + NS_IMETHOD SetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue); + NS_IMETHOD GetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue, + PRBool &aFirst, PRBool &aAny, PRBool &aAll); + NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty, const nsString *aAttribute); NS_IMETHOD DeleteSelection(nsIEditor::Direction aDir); NS_IMETHOD InsertText(const nsString& aStringToInsert); NS_IMETHOD InsertBreak(); @@ -100,11 +105,14 @@ protected: virtual void IsTextPropertySetByContent(nsIDOMNode *aNode, nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue, PRBool &aIsSet, nsIDOMNode **aStyleNode) const; virtual void IsTextStyleSet(nsIStyleContext *aSC, nsIAtom *aProperty, + const nsString *aAttributes, PRBool &aIsSet) const; NS_IMETHOD IsNodeInline(nsIDOMNode *aNode, PRBool &aIsInline) const; @@ -117,18 +125,22 @@ protected: nsIDOMNode *aParent, PRBool &aResult) const; - NS_IMETHOD SetTextPropertiesForNode(nsIDOMNode *aNode, - nsIDOMNode *aParent, - PRInt32 aStartOffset, - PRInt32 aEndOffset, - nsIAtom *aPropName); + NS_IMETHOD SetTextPropertiesForNode(nsIDOMNode *aNode, + nsIDOMNode *aParent, + PRInt32 aStartOffset, + PRInt32 aEndOffset, + nsIAtom *aPropName, + const nsString *aAttribute, + const nsString *aValue); - NS_IMETHOD SetTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, - PRInt32 aStartOffset, - nsIDOMNode *aEndNode, - PRInt32 aEndOffset, - nsIDOMNode *aParent, - nsIAtom *aPropName); + NS_IMETHOD SetTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, + PRInt32 aStartOffset, + nsIDOMNode *aEndNode, + PRInt32 aEndOffset, + nsIDOMNode *aParent, + nsIAtom *aPropName, + const nsString *aAttribute, + const nsString *aValue); NS_IMETHOD SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange, nsIDOMNode *aStartNode, @@ -136,20 +148,24 @@ protected: nsIDOMNode *aEndNode, PRInt32 aEndOffset, nsIDOMNode *aParent, - nsIAtom *aPropName); + nsIAtom *aPropName, + const nsString *aAttribute, + const nsString *aValue); - NS_IMETHOD RemoveTextPropertiesForNode(nsIDOMNode *aNode, - nsIDOMNode *aParent, - PRInt32 aStartOffset, - PRInt32 aEndOffset, - nsIAtom *aPropName); + NS_IMETHOD RemoveTextPropertiesForNode(nsIDOMNode *aNode, + nsIDOMNode *aParent, + PRInt32 aStartOffset, + PRInt32 aEndOffset, + nsIAtom *aPropName, + const nsString *aAttribute); - NS_IMETHOD RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, - PRInt32 aStartOffset, - nsIDOMNode *aEndNode, - PRInt32 aEndOffset, - nsIDOMNode *aParent, - nsIAtom *aPropName); + NS_IMETHOD RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, + PRInt32 aStartOffset, + nsIDOMNode *aEndNode, + PRInt32 aEndOffset, + nsIDOMNode *aParent, + nsIAtom *aPropName, + const nsString *aAttribute); NS_IMETHOD RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange, nsIDOMNode *aStartNode, @@ -157,11 +173,14 @@ protected: nsIDOMNode *aEndNode, PRInt32 aEndOffset, nsIDOMNode *aParent, - nsIAtom *aPropName); + nsIAtom *aPropName, + const nsString *aAttribute); - NS_IMETHOD SetTypeInStateForProperty(TypeInState &aTypeInState, nsIAtom *aPropName); + NS_IMETHOD SetTypeInStateForProperty(TypeInState &aTypeInState, + nsIAtom *aPropName, + const nsString *aAttribute); TypeInState GetTypeInState() { return mTypeInState;} diff --git a/editor/libeditor/base/nsEditor.cpp b/editor/libeditor/base/nsEditor.cpp index 8be8a419bb9..2228b617114 100644 --- a/editor/libeditor/base/nsEditor.cpp +++ b/editor/libeditor/base/nsEditor.cpp @@ -147,7 +147,7 @@ static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID); #define NS_ERROR_EDITOR_NO_TEXTNODE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,2) #ifdef NS_DEBUG_EDITOR -static PRBool gNoisy = PR_TRUE; +static PRBool gNoisy = PR_FALSE; #else static const PRBool gNoisy = PR_FALSE; #endif @@ -1848,7 +1848,7 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode, nsIDOMNode* aParent) { -printf("SplitNodeImpl: left=%p, right=%p, offset=%d\n", aNewLeftNode, aExistingRightNode, aOffset); + if (gNoisy) { printf("SplitNodeImpl: left=%p, right=%p, offset=%d\n", aNewLeftNode, aExistingRightNode, aOffset); } nsresult result; NS_ASSERTION(((nsnull!=aExistingRightNode) && diff --git a/editor/libeditor/base/nsIEditProperty.h b/editor/libeditor/base/nsIEditProperty.h index e7180bd7af7..502a26a4f89 100644 --- a/editor/libeditor/base/nsIEditProperty.h +++ b/editor/libeditor/base/nsIEditProperty.h @@ -22,6 +22,7 @@ #include "nsISupports.h" class nsIAtom; +class nsString; #define NS_IEDITPROPERTY_IID \ {/* 9875cd40-ca81-11d2-8f4d-006008159b0c*/ \ @@ -70,6 +71,9 @@ SUB places text in subscript style SUP places text in superscript style */ + /** special strings */ + static nsString *allProperties; // this magic string represents the union of all inline style tags + // XXX: end temp code }; diff --git a/editor/libeditor/html/nsEditProperty.cpp b/editor/libeditor/html/nsEditProperty.cpp index 5690a29a010..cb5d034fe55 100644 --- a/editor/libeditor/html/nsEditProperty.cpp +++ b/editor/libeditor/html/nsEditProperty.cpp @@ -17,6 +17,7 @@ */ #include "nsEditProperty.h" +#include "nsString.h" static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kIEditPropertyIID, NS_IEDITPROPERTY_IID); @@ -40,6 +41,7 @@ nsIAtom * nsIEditProperty::sub; nsIAtom * nsIEditProperty::sup; nsIAtom * nsIEditProperty::tt; nsIAtom * nsIEditProperty::u; +nsString * nsIEditProperty::allProperties; void nsEditProperty::InstanceInit() @@ -57,6 +59,7 @@ nsEditProperty::InstanceInit() nsIEditProperty::sup = NS_NewAtom("SUP"); nsIEditProperty::tt = NS_NewAtom("TT"); nsIEditProperty::u = NS_NewAtom("U"); + nsIEditProperty::allProperties = new nsString("moz_AllProperties"); } void @@ -75,6 +78,9 @@ nsEditProperty::InstanceShutdown() NS_IF_RELEASE(nsIEditProperty::sup); NS_IF_RELEASE(nsIEditProperty::tt); NS_IF_RELEASE(nsIEditProperty::u); + if (nsIEditProperty::allProperties) { + delete (nsIEditProperty::allProperties); + } } NS_IMETHODIMP diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp index 29bb4ca8135..de908312185 100644 --- a/editor/libeditor/html/nsHTMLEditor.cpp +++ b/editor/libeditor/html/nsHTMLEditor.cpp @@ -109,19 +109,24 @@ void nsHTMLEditor::InitRules() mRules->Init(this); } -NS_IMETHODIMP nsHTMLEditor::SetTextProperty(nsIAtom *aProperty) +NS_IMETHODIMP nsHTMLEditor::SetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue) { - return nsTextEditor::SetTextProperty(aProperty); + return nsTextEditor::SetTextProperty(aProperty, aAttribute, aValue); } -NS_IMETHODIMP nsHTMLEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll) +NS_IMETHODIMP nsHTMLEditor::GetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue, + PRBool &aFirst, PRBool &aAny, PRBool &aAll) { - return nsTextEditor::GetTextProperty(aProperty, aFirst, aAny, aAll); + return nsTextEditor::GetTextProperty(aProperty, aAttribute, aValue, aFirst, aAny, aAll); } -NS_IMETHODIMP nsHTMLEditor::RemoveTextProperty(nsIAtom *aProperty) +NS_IMETHODIMP nsHTMLEditor::RemoveTextProperty(nsIAtom *aProperty, const nsString *aAttribute) { - return nsTextEditor::RemoveTextProperty(aProperty); + return nsTextEditor::RemoveTextProperty(aProperty, aAttribute); } NS_IMETHODIMP nsHTMLEditor::DeleteSelection(nsIEditor::Direction aDir) diff --git a/editor/libeditor/html/nsHTMLEditor.h b/editor/libeditor/html/nsHTMLEditor.h index f2d9d111281..b7cc9424622 100644 --- a/editor/libeditor/html/nsHTMLEditor.h +++ b/editor/libeditor/html/nsHTMLEditor.h @@ -50,9 +50,13 @@ public: // Methods that are duplicates of nsTextEditor -- exposed here for convenience // Editing Operations - NS_IMETHOD SetTextProperty(nsIAtom *aProperty); - NS_IMETHOD GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll); - NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty); + NS_IMETHOD SetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue); + NS_IMETHOD GetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, const nsString *aValue, + PRBool &aFirst, PRBool &aAny, PRBool &aAll); + NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty, const nsString *aAttribute); NS_IMETHOD DeleteSelection(nsIEditor::Direction aDir); NS_IMETHOD InsertText(const nsString& aStringToInsert); NS_IMETHOD InsertBreak(); diff --git a/editor/libeditor/text/nsEditorEventListeners.cpp b/editor/libeditor/text/nsEditorEventListeners.cpp index 98d67d01576..eb42d0ce72c 100644 --- a/editor/libeditor/text/nsEditorEventListeners.cpp +++ b/editor/libeditor/text/nsEditorEventListeners.cpp @@ -28,6 +28,12 @@ #include "nsString.h" #include "nsIStringStream.h" +#ifdef NS_DEBUG +#ifdef EDITOR_SELFTEST +#include "TextEditorTest.h" +#endif +#endif + static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID); static NS_DEFINE_IID(kIDOMCharacterDataIID, NS_IDOMCHARACTERDATA_IID); @@ -338,12 +344,12 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr PRBool any = PR_FALSE; PRBool all = PR_FALSE; PRBool first = PR_FALSE; - mEditor->GetTextProperty(nsIEditProperty::i, first, any, all); + mEditor->GetTextProperty(nsIEditProperty::i, nsnull, nsnull, first, any, all); if (PR_FALSE==first) { - mEditor->SetTextProperty(nsIEditProperty::i); + mEditor->SetTextProperty(nsIEditProperty::i, nsnull, nsnull); } else { - mEditor->RemoveTextProperty(nsIEditProperty::i); + mEditor->RemoveTextProperty(nsIEditProperty::i, nsnull); } } } @@ -375,12 +381,12 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr PRBool any = PR_FALSE; PRBool all = PR_FALSE; PRBool first = PR_FALSE; - mEditor->GetTextProperty(nsIEditProperty::b, first, any, all); + mEditor->GetTextProperty(nsIEditProperty::b, nsnull, nsnull, first, any, all); if (PR_FALSE==first) { - mEditor->SetTextProperty(nsIEditProperty::b); + mEditor->SetTextProperty(nsIEditProperty::b, nsnull, nsnull); } else { - mEditor->RemoveTextProperty(nsIEditProperty::b); + mEditor->RemoveTextProperty(nsIEditProperty::b, nsnull); } } } @@ -398,17 +404,76 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr PRBool any = PR_FALSE; PRBool all = PR_FALSE; PRBool first = PR_FALSE; - mEditor->GetTextProperty(nsIEditProperty::u, first, any, all); + mEditor->GetTextProperty(nsIEditProperty::u, nsnull, nsnull, first, any, all); if (PR_FALSE==first) { - mEditor->SetTextProperty(nsIEditProperty::u); + mEditor->SetTextProperty(nsIEditProperty::u, nsnull, nsnull); } else { - mEditor->RemoveTextProperty(nsIEditProperty::u); + mEditor->RemoveTextProperty(nsIEditProperty::u, nsnull); } } } break; + + // hard-coded ChangeTextAttributes test -- font color red + case nsIDOMEvent::VK_1: + if (PR_TRUE==ctrlKey) + { + aProcessed=PR_TRUE; + if (mEditor) + { + // XXX: move this logic down into texteditor rules delegate + // should just call mEditor->ChangeTextProperty(prop) + PRBool any = PR_FALSE; + PRBool all = PR_FALSE; + PRBool first = PR_FALSE; + nsAutoString color = "color"; + nsAutoString value = "red"; + mEditor->SetTextProperty(nsIEditProperty::font, &color, &value); + } + } + break; + + // hard-coded ChangeTextAttributes test -- font color green + case nsIDOMEvent::VK_2: + if (PR_TRUE==ctrlKey) + { + aProcessed=PR_TRUE; + if (mEditor) + { + // XXX: move this logic down into texteditor rules delegate + // should just call mEditor->ChangeTextProperty(prop) + PRBool any = PR_FALSE; + PRBool all = PR_FALSE; + PRBool first = PR_FALSE; + nsAutoString color = "color"; + nsAutoString value = "green"; + mEditor->SetTextProperty(nsIEditProperty::font, &color, &value); + } + } + break; + +#ifdef NS_DEBUG +#ifdef EDITOR_SELFTEST + // hard-coded Text Editor Unit Test + case nsIDOMEvent::VK_T: + if (PR_TRUE==ctrlKey) + { + aProcessed=PR_TRUE; + if (mEditor) + { + TextEditorTest *tester = new TextEditorTest(); + if (tester) + { + tester->Run(mEditor); + } + } + } + break; +#endif +#endif + } } return NS_OK; diff --git a/editor/public/nsIHTMLEditor.h b/editor/public/nsIHTMLEditor.h index dc71991bd52..ecaf31ec8a5 100644 --- a/editor/public/nsIHTMLEditor.h +++ b/editor/public/nsIHTMLEditor.h @@ -49,9 +49,14 @@ public: NS_IMETHOD Init(nsIDOMDocument *aDoc, nsIPresShell *aPresShell )=0; // Methods shared with nsITextEditor (see nsITextEditor.h for details) - NS_IMETHOD SetTextProperty(nsIAtom *aProperty)=0; - NS_IMETHOD GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAll, PRBool &aAny)=0; - NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty)=0; + NS_IMETHOD SetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue)=0; + NS_IMETHOD GetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue, + PRBool &aFirst, PRBool &aAll, PRBool &aAny)=0; + NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty, const nsString *aAttribute)=0; NS_IMETHOD DeleteSelection(nsIEditor::Direction aDir)=0; NS_IMETHOD InsertText(const nsString& aStringToInsert)=0; NS_IMETHOD InsertBreak()=0; diff --git a/editor/public/nsITextEditor.h b/editor/public/nsITextEditor.h index 673caaa1952..89abd720faf 100644 --- a/editor/public/nsITextEditor.h +++ b/editor/public/nsITextEditor.h @@ -59,30 +59,46 @@ public: /** * SetTextProperties() sets the aggregate properties on the current selection * - * @param aPropList a list of properties to set across the selection - * NOTE: this method is experimental, expect it to change. + * @param aProperty the property to set on the selection + * @param aAttribute the attribute of the property, if applicable. May be null. + * Example: aProperty="font", aAttribute="color" + * @param aValue if aAttribute is not null, the value of the attribute. May be null. + * Example: aProperty="font", aAttribute="color", aValue="0x00FFFF" */ - NS_IMETHOD SetTextProperty(nsIAtom *aProperty)=0; + NS_IMETHOD SetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue)=0; /** * GetTextProperties() gets the aggregate properties of the current selection. * All object in the current selection are scanned and their attributes are * represented in a list of Property object. * - * @param aPropList A list of the various properties that are applied to the text content - * in the current selection. Each item in aPropList is an nsEditProperty. - * NOTE: this method is experimental, expect it to change. + * @param aProperty the property to get on the selection + * @param aAttribute the attribute of the property, if applicable. May be null. + * Example: aProperty="font", aAttribute="color" + * @param aValue if aAttribute is not null, the value of the attribute. May be null. + * Example: aProperty="font", aAttribute="color", aValue="0x00FFFF" + * @param aFirst [OUT] PR_TRUE if the first text node in the selection has the property + * @param aAny [OUT] PR_TRUE if any of the text nodes in the selection have the property + * @param aAll [OUT] PR_TRUE if all of the text nodes in the selection have the property */ - NS_IMETHOD GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll)=0; + NS_IMETHOD GetTextProperty(nsIAtom *aProperty, + const nsString *aAttribute, + const nsString *aValue, + PRBool &aFirst, PRBool &aAny, PRBool &aAll)=0; /** * RemoveTextProperties() deletes the properties from all text in the current selection. * If aProperty is not set on the selection, nothing is done. * - * @param aElement the content element to operate on - * @param aAttribute the string representation of the attribute to get + * @param aProperty the property to reomve from the selection + * @param aAttribute the attribute of the property, if applicable. May be null. + * Example: aProperty="font", aAttribute="color" + * nsIEditProperty::allAttributes is special. It indicates that + * all content-based text properties are to be removed from the selection. */ - NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty)=0; + NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty, const nsString *aAttribute)=0; /** * DeleteSelection removes all nodes in the current selection. diff --git a/editor/txmgr/src/nsTransactionManager.cpp b/editor/txmgr/src/nsTransactionManager.cpp index adf9e9031ac..5d1c5b99975 100644 --- a/editor/txmgr/src/nsTransactionManager.cpp +++ b/editor/txmgr/src/nsTransactionManager.cpp @@ -25,6 +25,12 @@ static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kITransactionManagerIID, NS_ITRANSACTIONMANAGER_IID); +#ifdef NS_DEBUG +static PRBool gNoisy = PR_FALSE; +#else +static const PRBool gNoisy = PR_FALSE; +#endif + nsTransactionManager::nsTransactionManager(PRInt32 aMaxTransactionCount) : mMaxTransactionCount(aMaxTransactionCount) { @@ -229,6 +235,7 @@ nsTransactionManager::Clear() nsresult nsTransactionManager::BeginBatch() { + if (gNoisy) { printf("Begin Batch\n"); } nsresult result; // We can batch independent transactions together by simply pushing @@ -248,6 +255,7 @@ nsTransactionManager::BeginBatch() nsresult nsTransactionManager::EndBatch() { + if (gNoisy) { printf("End Batch\n"); } nsTransactionItem *tx = 0; nsITransaction *ti = 0; nsresult result;