* beginnings of font handling. WIP, I did a big merge today and I'm checking in to synch up, not to announce new functionality here.

* added TextEditorTest.cpp, a unit test module for nsTextEditor.  It's use is actually commented out since my checkin is happening so late due
to all-day build bustage, and I don't have a Mac handy to verify.  With someone's Mac help tomorrow, I can turn it on.
* some minor bug fixes to property handling
This commit is contained in:
buster%netscape.com 1999-04-15 06:06:33 +00:00
Родитель 7cded6eeab
Коммит 9dbd182db1
19 изменённых файлов: 477 добавлений и 157 удалений

Просмотреть файл

@ -29,6 +29,7 @@ CPPSRCS = \
nsEditor.cpp \ nsEditor.cpp \
nsTextEditor.cpp \ nsTextEditor.cpp \
nsTextEditRules.cpp \ nsTextEditRules.cpp \
TextEditorTest.cpp \
nsHTMLEditRules.cpp \ nsHTMLEditRules.cpp \
nsEditorEventListeners.cpp \ nsEditorEventListeners.cpp \
nsEditProperty.cpp \ nsEditProperty.cpp \

Просмотреть файл

@ -25,6 +25,7 @@ CPPSRCS = \
nsTextEditor.cpp \ nsTextEditor.cpp \
nsTextEditRules.cpp \ nsTextEditRules.cpp \
nsHTMLEditRules.cpp \ nsHTMLEditRules.cpp \
TextEditorTest.cpp \
nsEditorEventListeners.cpp \ nsEditorEventListeners.cpp \
nsEditProperty.cpp \ nsEditProperty.cpp \
nsEditFactory.cpp \ nsEditFactory.cpp \
@ -60,6 +61,7 @@ CPP_OBJS = \
.\$(OBJDIR)\nsEditor.obj \ .\$(OBJDIR)\nsEditor.obj \
.\$(OBJDIR)\nsTextEditor.obj \ .\$(OBJDIR)\nsTextEditor.obj \
.\$(OBJDIR)\nsTextEditRules.obj \ .\$(OBJDIR)\nsTextEditRules.obj \
.\$(OBJDIR)\TextEditorTest.obj \
.\$(OBJDIR)\nsHTMLEditRules.obj \ .\$(OBJDIR)\nsHTMLEditRules.obj \
.\$(OBJDIR)\nsEditorEventListeners.obj \ .\$(OBJDIR)\nsEditorEventListeners.obj \
.\$(OBJDIR)\nsEditProperty.obj \ .\$(OBJDIR)\nsEditProperty.obj \

Просмотреть файл

@ -17,6 +17,7 @@
*/ */
#include "nsEditProperty.h" #include "nsEditProperty.h"
#include "nsString.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIEditPropertyIID, NS_IEDITPROPERTY_IID); static NS_DEFINE_IID(kIEditPropertyIID, NS_IEDITPROPERTY_IID);
@ -40,6 +41,7 @@ nsIAtom * nsIEditProperty::sub;
nsIAtom * nsIEditProperty::sup; nsIAtom * nsIEditProperty::sup;
nsIAtom * nsIEditProperty::tt; nsIAtom * nsIEditProperty::tt;
nsIAtom * nsIEditProperty::u; nsIAtom * nsIEditProperty::u;
nsString * nsIEditProperty::allProperties;
void void
nsEditProperty::InstanceInit() nsEditProperty::InstanceInit()
@ -57,6 +59,7 @@ nsEditProperty::InstanceInit()
nsIEditProperty::sup = NS_NewAtom("SUP"); nsIEditProperty::sup = NS_NewAtom("SUP");
nsIEditProperty::tt = NS_NewAtom("TT"); nsIEditProperty::tt = NS_NewAtom("TT");
nsIEditProperty::u = NS_NewAtom("U"); nsIEditProperty::u = NS_NewAtom("U");
nsIEditProperty::allProperties = new nsString("moz_AllProperties");
} }
void void
@ -75,6 +78,9 @@ nsEditProperty::InstanceShutdown()
NS_IF_RELEASE(nsIEditProperty::sup); NS_IF_RELEASE(nsIEditProperty::sup);
NS_IF_RELEASE(nsIEditProperty::tt); NS_IF_RELEASE(nsIEditProperty::tt);
NS_IF_RELEASE(nsIEditProperty::u); NS_IF_RELEASE(nsIEditProperty::u);
if (nsIEditProperty::allProperties) {
delete (nsIEditProperty::allProperties);
}
} }
NS_IMETHODIMP NS_IMETHODIMP

Просмотреть файл

@ -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) #define NS_ERROR_EDITOR_NO_TEXTNODE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,2)
#ifdef NS_DEBUG_EDITOR #ifdef NS_DEBUG_EDITOR
static PRBool gNoisy = PR_TRUE; static PRBool gNoisy = PR_FALSE;
#else #else
static const PRBool gNoisy = PR_FALSE; static const PRBool gNoisy = PR_FALSE;
#endif #endif
@ -1848,7 +1848,7 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
nsIDOMNode* aParent) 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; nsresult result;
NS_ASSERTION(((nsnull!=aExistingRightNode) && NS_ASSERTION(((nsnull!=aExistingRightNode) &&

Просмотреть файл

@ -28,6 +28,12 @@
#include "nsString.h" #include "nsString.h"
#include "nsIStringStream.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(kIDOMElementIID, NS_IDOMELEMENT_IID);
static NS_DEFINE_IID(kIDOMCharacterDataIID, NS_IDOMCHARACTERDATA_IID); static NS_DEFINE_IID(kIDOMCharacterDataIID, NS_IDOMCHARACTERDATA_IID);
@ -338,12 +344,12 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr
PRBool any = PR_FALSE; PRBool any = PR_FALSE;
PRBool all = PR_FALSE; PRBool all = PR_FALSE;
PRBool first = 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) { if (PR_FALSE==first) {
mEditor->SetTextProperty(nsIEditProperty::i); mEditor->SetTextProperty(nsIEditProperty::i, nsnull, nsnull);
} }
else { 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 any = PR_FALSE;
PRBool all = PR_FALSE; PRBool all = PR_FALSE;
PRBool first = 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) { if (PR_FALSE==first) {
mEditor->SetTextProperty(nsIEditProperty::b); mEditor->SetTextProperty(nsIEditProperty::b, nsnull, nsnull);
} }
else { 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 any = PR_FALSE;
PRBool all = PR_FALSE; PRBool all = PR_FALSE;
PRBool first = 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) { if (PR_FALSE==first) {
mEditor->SetTextProperty(nsIEditProperty::u); mEditor->SetTextProperty(nsIEditProperty::u, nsnull, nsnull);
} }
else { else {
mEditor->RemoveTextProperty(nsIEditProperty::u); mEditor->RemoveTextProperty(nsIEditProperty::u, nsnull);
} }
} }
} }
break; 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; return NS_OK;

Просмотреть файл

@ -109,19 +109,24 @@ void nsHTMLEditor::InitRules()
mRules->Init(this); 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) NS_IMETHODIMP nsHTMLEditor::DeleteSelection(nsIEditor::Direction aDir)

Просмотреть файл

@ -50,9 +50,13 @@ public:
// Methods that are duplicates of nsTextEditor -- exposed here for convenience // Methods that are duplicates of nsTextEditor -- exposed here for convenience
// Editing Operations // Editing Operations
NS_IMETHOD SetTextProperty(nsIAtom *aProperty); NS_IMETHOD SetTextProperty(nsIAtom *aProperty,
NS_IMETHOD GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll); const nsString *aAttribute,
NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty); 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 DeleteSelection(nsIEditor::Direction aDir);
NS_IMETHOD InsertText(const nsString& aStringToInsert); NS_IMETHOD InsertText(const nsString& aStringToInsert);
NS_IMETHOD InsertBreak(); NS_IMETHOD InsertBreak();

Просмотреть файл

@ -22,6 +22,7 @@
#include "nsISupports.h" #include "nsISupports.h"
class nsIAtom; class nsIAtom;
class nsString;
#define NS_IEDITPROPERTY_IID \ #define NS_IEDITPROPERTY_IID \
{/* 9875cd40-ca81-11d2-8f4d-006008159b0c*/ \ {/* 9875cd40-ca81-11d2-8f4d-006008159b0c*/ \
@ -70,6 +71,9 @@ SUB places text in subscript style
SUP places text in superscript 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 // XXX: end temp code
}; };

Просмотреть файл

@ -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) if (!aProperty)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
@ -329,10 +331,20 @@ NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty)
if (PR_TRUE==isCollapsed) if (PR_TRUE==isCollapsed)
{ {
// manipulating text attributes on a collapsed selection only sets state for the next text insertion // manipulating text attributes on a collapsed selection only sets state for the next text insertion
SetTypeInStateForProperty(mTypeInState, aProperty); SetTypeInStateForProperty(mTypeInState, aProperty, aAttribute);
} }
else else
{ {
// remember start and end points of selection
// XXX: this won't work for discontiguous selections
nsCOMPtr<nsIDOMNode> selStartNode;
PRInt32 selStartOffset;
nsCOMPtr<nsIDOMNode> 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(); nsEditor::BeginTransaction();
nsCOMPtr<nsIEnumerator> enumerator; nsCOMPtr<nsIEnumerator> enumerator;
enumerator = do_QueryInterface(selection); enumerator = do_QueryInterface(selection);
@ -360,7 +372,7 @@ NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty)
startParent->GetParentNode(getter_AddRefs(commonParent)); startParent->GetParentNode(getter_AddRefs(commonParent));
result = SetTextPropertiesForNode(startParent, commonParent, result = SetTextPropertiesForNode(startParent, commonParent,
startOffset, endOffset, startOffset, endOffset,
aProperty); aProperty, aAttribute, aValue);
} }
else else
{ {
@ -385,7 +397,7 @@ NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty)
result = SetTextPropertiesForNodesWithSameParent(startParent,startOffset, result = SetTextPropertiesForNodesWithSameParent(startParent,startOffset,
endParent, endOffset, endParent, endOffset,
commonParent, commonParent,
aProperty); aProperty, aAttribute, aValue);
} }
else else
{ // the range is between 2 nodes that have no simple relationship { // the range is between 2 nodes that have no simple relationship
@ -393,7 +405,7 @@ NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty)
startParent,startOffset, startParent,startOffset,
endParent, endOffset, endParent, endOffset,
commonParent, commonParent,
aProperty); aProperty, aAttribute, aValue);
} }
} }
} }
@ -420,7 +432,10 @@ NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty)
return result; 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) if (!aProperty)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
@ -497,7 +512,7 @@ NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aFirst,
{ {
PRBool isSet; PRBool isSet;
nsCOMPtr<nsIDOMNode>resultNode; nsCOMPtr<nsIDOMNode>resultNode;
IsTextPropertySetByContent(node, aProperty, isSet, getter_AddRefs(resultNode)); IsTextPropertySetByContent(node, aProperty, aAttribute, aValue, isSet, getter_AddRefs(resultNode));
if (PR_TRUE==first) if (PR_TRUE==first)
{ {
aFirst = isSet; aFirst = isSet;
@ -513,7 +528,7 @@ NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aFirst,
} }
} }
iter->Next(); 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, void nsTextEditor::IsTextStyleSet(nsIStyleContext *aSC,
nsIAtom *aProperty, nsIAtom *aProperty,
const nsString *aAttribute,
PRBool &aIsSet) const PRBool &aIsSet) const
{ {
aIsSet = PR_FALSE; aIsSet = PR_FALSE;
@ -542,13 +558,17 @@ void nsTextEditor::IsTextStyleSet(nsIStyleContext *aSC,
} }
} }
void nsTextEditor::IsTextPropertySetByContent(nsIDOMNode *aNode, // this will NOT find aAttribute unless aAttribute has a non-null value
nsIAtom *aProperty, // so singleton attributes like <Table border> will not be matched!
PRBool &aIsSet, void nsTextEditor::IsTextPropertySetByContent(nsIDOMNode *aNode,
nsIDOMNode **aStyleNode) const nsIAtom *aProperty,
const nsString *aAttribute,
const nsString *aValue,
PRBool &aIsSet,
nsIDOMNode **aStyleNode) const
{ {
nsresult result; nsresult result;
aIsSet = PR_FALSE; aIsSet = PR_FALSE; // must be initialized to false for code below to work
nsAutoString propName; nsAutoString propName;
aProperty->ToString(propName); aProperty->ToString(propName);
nsCOMPtr<nsIDOMNode>parent; nsCOMPtr<nsIDOMNode>parent;
@ -563,8 +583,32 @@ void nsTextEditor::IsTextPropertySetByContent(nsIDOMNode *aNode,
element->GetTagName(tag); element->GetTagName(tag);
if (propName.Equals(tag)) if (propName.Equals(tag))
{ {
aIsSet = PR_TRUE; PRBool found = PR_FALSE;
break; 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;
}
} }
} }
nsCOMPtr<nsIDOMNode>temp; nsCOMPtr<nsIDOMNode>temp;
@ -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) if (!aProperty)
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
@ -603,11 +647,13 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty)
if (PR_TRUE==isCollapsed) if (PR_TRUE==isCollapsed)
{ {
// manipulating text attributes on a collapsed selection only sets state for the next text insertion // manipulating text attributes on a collapsed selection only sets state for the next text insertion
SetTypeInStateForProperty(mTypeInState, aProperty); SetTypeInStateForProperty(mTypeInState, aProperty, aAttribute);
} }
else else
{ {
nsEditor::BeginTransaction(); nsEditor::BeginTransaction();
nsCOMPtr<nsIDOMNode> startParent, endParent;
PRInt32 startOffset, endOffset;
nsCOMPtr<nsIEnumerator> enumerator; nsCOMPtr<nsIEnumerator> enumerator;
enumerator = do_QueryInterface(selection); enumerator = do_QueryInterface(selection);
if (enumerator) if (enumerator)
@ -622,10 +668,8 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty)
result = range->GetCommonParent(getter_AddRefs(commonParent)); result = range->GetCommonParent(getter_AddRefs(commonParent));
if ((NS_SUCCEEDED(result)) && commonParent) if ((NS_SUCCEEDED(result)) && commonParent)
{ {
PRInt32 startOffset, endOffset;
range->GetStartOffset(&startOffset); range->GetStartOffset(&startOffset);
range->GetEndOffset(&endOffset); range->GetEndOffset(&endOffset);
nsCOMPtr<nsIDOMNode> startParent; nsCOMPtr<nsIDOMNode> endParent;
range->GetStartParent(getter_AddRefs(startParent)); range->GetStartParent(getter_AddRefs(startParent));
range->GetEndParent(getter_AddRefs(endParent)); range->GetEndParent(getter_AddRefs(endParent));
if (startParent.get()==endParent.get()) if (startParent.get()==endParent.get())
@ -634,7 +678,7 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty)
startParent->GetParentNode(getter_AddRefs(commonParent)); startParent->GetParentNode(getter_AddRefs(commonParent));
result = RemoveTextPropertiesForNode(startParent, commonParent, result = RemoveTextPropertiesForNode(startParent, commonParent,
startOffset, endOffset, startOffset, endOffset,
aProperty); aProperty, nsnull);
} }
else else
{ {
@ -659,7 +703,7 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty)
result = RemoveTextPropertiesForNodesWithSameParent(startParent,startOffset, result = RemoveTextPropertiesForNodesWithSameParent(startParent,startOffset,
endParent, endOffset, endParent, endOffset,
commonParent, commonParent,
aProperty); aProperty, nsnull);
} }
else else
{ // the range is between 2 nodes that have no simple relationship { // the range is between 2 nodes that have no simple relationship
@ -667,7 +711,7 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty)
startParent,startOffset, startParent,startOffset,
endParent, endOffset, endParent, endOffset,
commonParent, commonParent,
aProperty); aProperty, nsnull);
} }
} }
} }
@ -684,10 +728,11 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty)
} }
} }
nsEditor::EndTransaction(); nsEditor::EndTransaction();
} if (NS_SUCCEEDED(result))
if (NS_SUCCEEDED(result)) {
{ // set the selection selection->Collapse(startParent, startOffset);
// XXX: can't do anything until I can create ranges selection->Extend(endParent, endOffset);
}
} }
} }
return result; return result;
@ -1065,11 +1110,13 @@ NS_IMETHODIMP nsTextEditor::OutputHTML(nsString& aOutputString)
} }
NS_IMETHODIMP nsTextEditor::SetTextPropertiesForNode(nsIDOMNode *aNode, NS_IMETHODIMP nsTextEditor::SetTextPropertiesForNode(nsIDOMNode *aNode,
nsIDOMNode *aParent, nsIDOMNode *aParent,
PRInt32 aStartOffset, PRInt32 aStartOffset,
PRInt32 aEndOffset, PRInt32 aEndOffset,
nsIAtom *aPropName) nsIAtom *aPropName,
const nsString *aAttribute,
const nsString *aValue)
{ {
if (gNoisy) { printf("nsTextEditor::SetTextPropertyForNode\n"); } if (gNoisy) { printf("nsTextEditor::SetTextPropertyForNode\n"); }
nsresult result=NS_OK; nsresult result=NS_OK;
@ -1080,50 +1127,95 @@ NS_IMETHODIMP nsTextEditor::SetTextPropertiesForNode(nsIDOMNode *aNode,
PRBool textPropertySet; PRBool textPropertySet;
nsCOMPtr<nsIDOMNode>resultNode; nsCOMPtr<nsIDOMNode>resultNode;
IsTextPropertySetByContent(aNode, aPropName, textPropertySet, getter_AddRefs(resultNode)); IsTextPropertySetByContent(aNode, aPropName, aAttribute, aValue, textPropertySet, getter_AddRefs(resultNode));
if (PR_FALSE==textPropertySet) if (PR_FALSE==textPropertySet)
{ {
PRUint32 count; PRUint32 count;
nodeAsChar->GetLength(&count); nodeAsChar->GetLength(&count);
nsCOMPtr<nsIDOMNode>newTextNode; // this will be the text node we move into the new style node nsCOMPtr<nsIDOMNode>newTextNode; // 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) if (aStartOffset!=0)
{ {
result = nsEditor::SplitNode(aNode, aStartOffset, getter_AddRefs(newTextNode)); 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 (NS_SUCCEEDED(result))
{ {
if (aEndOffset!=(PRInt32)count) if (aEndOffset!=(PRInt32)count)
{ {
result = nsEditor::SplitNode(aNode, aEndOffset-aStartOffset, getter_AddRefs(newTextNode)); 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 else
{ {
newTextNode = do_QueryInterface(aNode); 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)) if (NS_SUCCEEDED(result))
{ {
nsAutoString tag; // optimization: if all we're doing is changing a value for an existing attribute for the
aPropName->ToString(tag); // entire selection, then just twiddle the existing style node
PRInt32 offsetInParent; PRBool done = PR_FALSE; // set to true in optimized case if we can really do the optimization
result = nsIEditorSupport::GetChildOffset(aNode, aParent, offsetInParent); if (aAttribute && aValue && (0==aStartOffset) && (aEndOffset==(PRInt32)count))
if (NS_SUCCEEDED(result))
{ {
nsCOMPtr<nsIDOMNode>newStyleNode; // ??? can we really compute this?
result = nsEditor::CreateNode(tag, aParent, offsetInParent, getter_AddRefs(newStyleNode)); }
if (NS_SUCCEEDED(result)) if (PR_FALSE==done)
{
nsCOMPtr<nsIDOMCharacterData>newTextNodeAsChar;
newTextNodeAsChar = do_QueryInterface(newTextNode);
PRUint32 newTextNodeLength;
newTextNodeAsChar->GetLength(&newTextNodeLength);
if (0==newTextNodeLength)
{ {
result = nsEditor::DeleteNode(newTextNode); result = nsEditor::DeleteNode(newTextNode);
if (NS_SUCCEEDED(result)) { }
result = nsEditor::InsertNode(newTextNode, newStyleNode, 0); else
if (NS_SUCCEEDED(result)) {
{ // set the selection nsAutoString tag;
nsCOMPtr<nsIDOMSelection>selection; aPropName->ToString(tag);
result = nsEditor::GetSelection(getter_AddRefs(selection)); PRInt32 offsetInParent;
if (NS_SUCCEEDED(result)) { result = nsIEditorSupport::GetChildOffset(aNode, aParent, offsetInParent);
selection->Collapse(newTextNode, 0); if (NS_SUCCEEDED(result))
PRInt32 endOffset = aEndOffset-aStartOffset; {
selection->Extend(newTextNode, endOffset); nsCOMPtr<nsIDOMNode>newStyleNode;
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<nsIDOMElement> 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
nsCOMPtr<nsIDOMSelection>selection;
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 */ /* this should only get called if the only intervening nodes are inline style nodes */
NS_IMETHODIMP NS_IMETHODIMP
nsTextEditor::SetTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, nsTextEditor::SetTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode,
PRInt32 aStartOffset, PRInt32 aStartOffset,
nsIDOMNode *aEndNode, nsIDOMNode *aEndNode,
PRInt32 aEndOffset, PRInt32 aEndOffset,
nsIDOMNode *aParent, nsIDOMNode *aParent,
nsIAtom *aPropName) nsIAtom *aPropName,
const nsString *aAttribute,
const nsString *aValue)
{ {
if (gNoisy) { printf("nsTextEditor::SetTextPropertiesForNodesWithSameParent\n"); } if (gNoisy) { printf("nsTextEditor::SetTextPropertiesForNodesWithSameParent\n"); }
nsresult result=NS_OK; nsresult result=NS_OK;
PRBool textPropertySet; PRBool textPropertySet;
nsCOMPtr<nsIDOMNode>resultNode; nsCOMPtr<nsIDOMNode>resultNode;
IsTextPropertySetByContent(aStartNode, aPropName, textPropertySet, getter_AddRefs(resultNode)); IsTextPropertySetByContent(aStartNode, aPropName, aAttribute, aValue, textPropertySet, getter_AddRefs(resultNode));
if (PR_FALSE==textPropertySet) if (PR_FALSE==textPropertySet)
{ {
nsCOMPtr<nsIDOMNode>newLeftTextNode; // this will be the middle text node nsCOMPtr<nsIDOMNode>newLeftTextNode; // this will be the middle text node
@ -1350,7 +1444,9 @@ nsTextEditor::SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange,
nsIDOMNode *aEndNode, nsIDOMNode *aEndNode,
PRInt32 aEndOffset, PRInt32 aEndOffset,
nsIDOMNode *aParent, nsIDOMNode *aParent,
nsIAtom *aPropName) nsIAtom *aPropName,
const nsString *aAttribute,
const nsString *aValue)
{ {
if (gNoisy) { printf("nsTextEditor::SetTextPropertiesForNodeWithDifferentParents\n"); } if (gNoisy) { printf("nsTextEditor::SetTextPropertiesForNodeWithDifferentParents\n"); }
nsresult result=NS_OK; nsresult result=NS_OK;
@ -1394,7 +1490,7 @@ nsTextEditor::SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange,
node = do_QueryInterface(content); node = do_QueryInterface(content);
PRBool textPropertySet; PRBool textPropertySet;
nsCOMPtr<nsIDOMNode>resultNode; nsCOMPtr<nsIDOMNode>resultNode;
IsTextPropertySetByContent(node, aPropName, textPropertySet, getter_AddRefs(resultNode)); IsTextPropertySetByContent(node, aPropName, aAttribute, aValue, textPropertySet, getter_AddRefs(resultNode));
if (PR_FALSE==textPropertySet) if (PR_FALSE==textPropertySet)
{ {
nsCOMPtr<nsIDOMNode>parent; nsCOMPtr<nsIDOMNode>parent;
@ -1435,7 +1531,7 @@ nsTextEditor::SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
PRUint32 count; PRUint32 count;
nodeAsChar->GetLength(&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 // create a style node for the text in the end parent
result = aEndNode->GetParentNode(getter_AddRefs(parent)); result = aEndNode->GetParentNode(getter_AddRefs(parent));
@ -1446,7 +1542,7 @@ nsTextEditor::SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange,
if (!nodeAsChar) if (!nodeAsChar)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
nodeAsChar->GetLength(&count); nodeAsChar->GetLength(&count);
result = SetTextPropertiesForNode(aEndNode, parent, 0, aEndOffset, aPropName); result = SetTextPropertiesForNode(aEndNode, parent, 0, aEndOffset, aPropName, aAttribute, aValue);
return result; return result;
} }
@ -1455,7 +1551,8 @@ NS_IMETHODIMP nsTextEditor::RemoveTextPropertiesForNode(nsIDOMNode *aNode,
nsIDOMNode *aParent, nsIDOMNode *aParent,
PRInt32 aStartOffset, PRInt32 aStartOffset,
PRInt32 aEndOffset, PRInt32 aEndOffset,
nsIAtom *aPropName) nsIAtom *aPropName,
const nsString *aAttribute)
{ {
if (gNoisy) { printf("nsTextEditor::RemoveTextPropertyForNode\n"); } if (gNoisy) { printf("nsTextEditor::RemoveTextPropertyForNode\n"); }
nsresult result=NS_OK; nsresult result=NS_OK;
@ -1463,7 +1560,7 @@ NS_IMETHODIMP nsTextEditor::RemoveTextPropertiesForNode(nsIDOMNode *aNode,
nodeAsChar = do_QueryInterface(aNode); nodeAsChar = do_QueryInterface(aNode);
PRBool textPropertySet; PRBool textPropertySet;
nsCOMPtr<nsIDOMNode>resultNode; nsCOMPtr<nsIDOMNode>resultNode;
IsTextPropertySetByContent(aNode, aPropName, textPropertySet, getter_AddRefs(resultNode)); IsTextPropertySetByContent(aNode, aPropName, aAttribute, nsnull, textPropertySet, getter_AddRefs(resultNode));
if (PR_TRUE==textPropertySet) if (PR_TRUE==textPropertySet)
{ {
nsCOMPtr<nsIDOMNode>parent; // initially set to first interior parent node to process nsCOMPtr<nsIDOMNode>parent; // initially set to first interior parent node to process
@ -1670,7 +1767,8 @@ nsTextEditor::RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode,
nsIDOMNode *aEndNode, nsIDOMNode *aEndNode,
PRInt32 aEndOffset, PRInt32 aEndOffset,
nsIDOMNode *aParent, nsIDOMNode *aParent,
nsIAtom *aPropName) nsIAtom *aPropName,
const nsString *aAttribute)
{ {
if (gNoisy) { printf("nsTextEditor::RemoveTextPropertiesForNodesWithSameParent\n"); } if (gNoisy) { printf("nsTextEditor::RemoveTextPropertiesForNodesWithSameParent\n"); }
nsresult result=NS_OK; nsresult result=NS_OK;
@ -1711,7 +1809,7 @@ nsTextEditor::RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode,
} }
if (NS_SUCCEEDED(result)) { if (NS_SUCCEEDED(result)) {
siblingNode->GetParentNode(getter_AddRefs(parentNode)); siblingNode->GetParentNode(getter_AddRefs(parentNode));
result = RemoveTextPropertiesForNode(siblingNode, parentNode, 0, childCount, aPropName); result = RemoveTextPropertiesForNode(siblingNode, parentNode, 0, childCount, aPropName, aAttribute);
} }
} }
siblingNode = do_QueryInterface(nextSiblingNode); siblingNode = do_QueryInterface(nextSiblingNode);
@ -1731,7 +1829,7 @@ nsTextEditor::RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode,
} }
result = aStartNode->GetParentNode(getter_AddRefs(parentNode)); result = aStartNode->GetParentNode(getter_AddRefs(parentNode));
if (NS_SUCCEEDED(result)) { if (NS_SUCCEEDED(result)) {
result = RemoveTextPropertiesForNode(aStartNode, parentNode, startOffset, endOffset, aPropName); result = RemoveTextPropertiesForNode(aStartNode, parentNode, startOffset, endOffset, aPropName, aAttribute);
} }
} }
if (NS_SUCCEEDED(result)) if (NS_SUCCEEDED(result))
@ -1741,7 +1839,7 @@ nsTextEditor::RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode,
endOffset = aEndOffset; endOffset = aEndOffset;
result = aEndNode->GetParentNode(getter_AddRefs(parentNode)); result = aEndNode->GetParentNode(getter_AddRefs(parentNode));
if (NS_SUCCEEDED(result)) { if (NS_SUCCEEDED(result)) {
result = RemoveTextPropertiesForNode(aEndNode, parentNode, startOffset, endOffset, aPropName); result = RemoveTextPropertiesForNode(aEndNode, parentNode, startOffset, endOffset, aPropName, aAttribute);
} }
} }
return result; return result;
@ -1754,7 +1852,8 @@ nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRang
nsIDOMNode *aEndNode, nsIDOMNode *aEndNode,
PRInt32 aEndOffset, PRInt32 aEndOffset,
nsIDOMNode *aParent, nsIDOMNode *aParent,
nsIAtom *aPropName) nsIAtom *aPropName,
const nsString *aAttribute)
{ {
if (gNoisy) { printf("nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents\n"); } if (gNoisy) { printf("nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents\n"); }
nsresult result=NS_OK; nsresult result=NS_OK;
@ -1776,8 +1875,8 @@ nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRang
nodeAsChar = do_QueryInterface(aStartNode); nodeAsChar = do_QueryInterface(aStartNode);
if (!nodeAsChar) { return NS_ERROR_FAILURE; } if (!nodeAsChar) { return NS_ERROR_FAILURE; }
nodeAsChar->GetLength(&count); nodeAsChar->GetLength(&count);
if (aStartOffset!=count) { // only do this if at least one child is selected if ((PRUint32)aStartOffset!=count) { // only do this if at least one child is selected
result = RemoveTextPropertiesForNode(aStartNode, parent, aStartOffset, count, aPropName); result = RemoveTextPropertiesForNode(aStartNode, parent, aStartOffset, count, aPropName, aAttribute);
if (0!=aStartOffset) { if (0!=aStartOffset) {
rangeStartOffset = 0; // we split aStartNode at aStartOffset and it is the right node now 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; } if (!nodeAsChar) { return NS_ERROR_FAILURE; }
nodeAsChar->GetLength(&count); nodeAsChar->GetLength(&count);
if (aEndOffset!=0) { // only do this if at least one child is selected 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) { if (0!=aEndOffset) {
rangeEndOffset = 0; // we split aEndNode at aEndOffset and it is the right node now rangeEndOffset = 0; // we split aEndNode at aEndOffset and it is the right node now
} }
@ -1934,7 +2033,9 @@ nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRang
} }
NS_IMETHODIMP NS_IMETHODIMP
nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState, nsIAtom *aPropName) nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState,
nsIAtom *aPropName,
const nsString *aAttribute)
{ {
if (!aPropName) { if (!aPropName) {
return NS_ERROR_NULL_POINTER; return NS_ERROR_NULL_POINTER;
@ -1950,7 +2051,7 @@ nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState, nsIAtom *aPro
PRBool any = PR_FALSE; PRBool any = PR_FALSE;
PRBool all = PR_FALSE; PRBool all = PR_FALSE;
PRBool first = 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); aTypeInState.SetBold(!any);
} }
} }
@ -1965,7 +2066,7 @@ nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState, nsIAtom *aPro
PRBool any = PR_FALSE; PRBool any = PR_FALSE;
PRBool all = PR_FALSE; PRBool all = PR_FALSE;
PRBool first = 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); aTypeInState.SetItalic(!any);
} }
} }
@ -1980,7 +2081,7 @@ nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState, nsIAtom *aPro
PRBool any = PR_FALSE; PRBool any = PR_FALSE;
PRBool all = PR_FALSE; PRBool all = PR_FALSE;
PRBool first = 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); aTypeInState.SetUnderline(!any);
} }
} }

Просмотреть файл

@ -51,9 +51,14 @@ public:
NS_IMETHOD Init(nsIDOMDocument *aDoc, nsIPresShell *aPresShell); NS_IMETHOD Init(nsIDOMDocument *aDoc, nsIPresShell *aPresShell);
// Editing Operations // Editing Operations
NS_IMETHOD SetTextProperty(nsIAtom *aProperty); NS_IMETHOD SetTextProperty(nsIAtom *aProperty,
NS_IMETHOD GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll); const nsString *aAttribute,
NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty); 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 DeleteSelection(nsIEditor::Direction aDir);
NS_IMETHOD InsertText(const nsString& aStringToInsert); NS_IMETHOD InsertText(const nsString& aStringToInsert);
NS_IMETHOD InsertBreak(); NS_IMETHOD InsertBreak();
@ -100,11 +105,14 @@ protected:
virtual void IsTextPropertySetByContent(nsIDOMNode *aNode, virtual void IsTextPropertySetByContent(nsIDOMNode *aNode,
nsIAtom *aProperty, nsIAtom *aProperty,
const nsString *aAttribute,
const nsString *aValue,
PRBool &aIsSet, PRBool &aIsSet,
nsIDOMNode **aStyleNode) const; nsIDOMNode **aStyleNode) const;
virtual void IsTextStyleSet(nsIStyleContext *aSC, virtual void IsTextStyleSet(nsIStyleContext *aSC,
nsIAtom *aProperty, nsIAtom *aProperty,
const nsString *aAttributes,
PRBool &aIsSet) const; PRBool &aIsSet) const;
NS_IMETHOD IsNodeInline(nsIDOMNode *aNode, PRBool &aIsInline) const; NS_IMETHOD IsNodeInline(nsIDOMNode *aNode, PRBool &aIsInline) const;
@ -117,18 +125,22 @@ protected:
nsIDOMNode *aParent, nsIDOMNode *aParent,
PRBool &aResult) const; PRBool &aResult) const;
NS_IMETHOD SetTextPropertiesForNode(nsIDOMNode *aNode, NS_IMETHOD SetTextPropertiesForNode(nsIDOMNode *aNode,
nsIDOMNode *aParent, nsIDOMNode *aParent,
PRInt32 aStartOffset, PRInt32 aStartOffset,
PRInt32 aEndOffset, PRInt32 aEndOffset,
nsIAtom *aPropName); nsIAtom *aPropName,
const nsString *aAttribute,
const nsString *aValue);
NS_IMETHOD SetTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, NS_IMETHOD SetTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode,
PRInt32 aStartOffset, PRInt32 aStartOffset,
nsIDOMNode *aEndNode, nsIDOMNode *aEndNode,
PRInt32 aEndOffset, PRInt32 aEndOffset,
nsIDOMNode *aParent, nsIDOMNode *aParent,
nsIAtom *aPropName); nsIAtom *aPropName,
const nsString *aAttribute,
const nsString *aValue);
NS_IMETHOD SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange, NS_IMETHOD SetTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange,
nsIDOMNode *aStartNode, nsIDOMNode *aStartNode,
@ -136,20 +148,24 @@ protected:
nsIDOMNode *aEndNode, nsIDOMNode *aEndNode,
PRInt32 aEndOffset, PRInt32 aEndOffset,
nsIDOMNode *aParent, nsIDOMNode *aParent,
nsIAtom *aPropName); nsIAtom *aPropName,
const nsString *aAttribute,
const nsString *aValue);
NS_IMETHOD RemoveTextPropertiesForNode(nsIDOMNode *aNode, NS_IMETHOD RemoveTextPropertiesForNode(nsIDOMNode *aNode,
nsIDOMNode *aParent, nsIDOMNode *aParent,
PRInt32 aStartOffset, PRInt32 aStartOffset,
PRInt32 aEndOffset, PRInt32 aEndOffset,
nsIAtom *aPropName); nsIAtom *aPropName,
const nsString *aAttribute);
NS_IMETHOD RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode, NS_IMETHOD RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode,
PRInt32 aStartOffset, PRInt32 aStartOffset,
nsIDOMNode *aEndNode, nsIDOMNode *aEndNode,
PRInt32 aEndOffset, PRInt32 aEndOffset,
nsIDOMNode *aParent, nsIDOMNode *aParent,
nsIAtom *aPropName); nsIAtom *aPropName,
const nsString *aAttribute);
NS_IMETHOD RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange, NS_IMETHOD RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange,
nsIDOMNode *aStartNode, nsIDOMNode *aStartNode,
@ -157,11 +173,14 @@ protected:
nsIDOMNode *aEndNode, nsIDOMNode *aEndNode,
PRInt32 aEndOffset, PRInt32 aEndOffset,
nsIDOMNode *aParent, 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;} TypeInState GetTypeInState() { return mTypeInState;}

Просмотреть файл

@ -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) #define NS_ERROR_EDITOR_NO_TEXTNODE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_EDITOR,2)
#ifdef NS_DEBUG_EDITOR #ifdef NS_DEBUG_EDITOR
static PRBool gNoisy = PR_TRUE; static PRBool gNoisy = PR_FALSE;
#else #else
static const PRBool gNoisy = PR_FALSE; static const PRBool gNoisy = PR_FALSE;
#endif #endif
@ -1848,7 +1848,7 @@ nsEditor::SplitNodeImpl(nsIDOMNode * aExistingRightNode,
nsIDOMNode* aParent) 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; nsresult result;
NS_ASSERTION(((nsnull!=aExistingRightNode) && NS_ASSERTION(((nsnull!=aExistingRightNode) &&

Просмотреть файл

@ -22,6 +22,7 @@
#include "nsISupports.h" #include "nsISupports.h"
class nsIAtom; class nsIAtom;
class nsString;
#define NS_IEDITPROPERTY_IID \ #define NS_IEDITPROPERTY_IID \
{/* 9875cd40-ca81-11d2-8f4d-006008159b0c*/ \ {/* 9875cd40-ca81-11d2-8f4d-006008159b0c*/ \
@ -70,6 +71,9 @@ SUB places text in subscript style
SUP places text in superscript 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 // XXX: end temp code
}; };

Просмотреть файл

@ -17,6 +17,7 @@
*/ */
#include "nsEditProperty.h" #include "nsEditProperty.h"
#include "nsString.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIEditPropertyIID, NS_IEDITPROPERTY_IID); static NS_DEFINE_IID(kIEditPropertyIID, NS_IEDITPROPERTY_IID);
@ -40,6 +41,7 @@ nsIAtom * nsIEditProperty::sub;
nsIAtom * nsIEditProperty::sup; nsIAtom * nsIEditProperty::sup;
nsIAtom * nsIEditProperty::tt; nsIAtom * nsIEditProperty::tt;
nsIAtom * nsIEditProperty::u; nsIAtom * nsIEditProperty::u;
nsString * nsIEditProperty::allProperties;
void void
nsEditProperty::InstanceInit() nsEditProperty::InstanceInit()
@ -57,6 +59,7 @@ nsEditProperty::InstanceInit()
nsIEditProperty::sup = NS_NewAtom("SUP"); nsIEditProperty::sup = NS_NewAtom("SUP");
nsIEditProperty::tt = NS_NewAtom("TT"); nsIEditProperty::tt = NS_NewAtom("TT");
nsIEditProperty::u = NS_NewAtom("U"); nsIEditProperty::u = NS_NewAtom("U");
nsIEditProperty::allProperties = new nsString("moz_AllProperties");
} }
void void
@ -75,6 +78,9 @@ nsEditProperty::InstanceShutdown()
NS_IF_RELEASE(nsIEditProperty::sup); NS_IF_RELEASE(nsIEditProperty::sup);
NS_IF_RELEASE(nsIEditProperty::tt); NS_IF_RELEASE(nsIEditProperty::tt);
NS_IF_RELEASE(nsIEditProperty::u); NS_IF_RELEASE(nsIEditProperty::u);
if (nsIEditProperty::allProperties) {
delete (nsIEditProperty::allProperties);
}
} }
NS_IMETHODIMP NS_IMETHODIMP

Просмотреть файл

@ -109,19 +109,24 @@ void nsHTMLEditor::InitRules()
mRules->Init(this); 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) NS_IMETHODIMP nsHTMLEditor::DeleteSelection(nsIEditor::Direction aDir)

Просмотреть файл

@ -50,9 +50,13 @@ public:
// Methods that are duplicates of nsTextEditor -- exposed here for convenience // Methods that are duplicates of nsTextEditor -- exposed here for convenience
// Editing Operations // Editing Operations
NS_IMETHOD SetTextProperty(nsIAtom *aProperty); NS_IMETHOD SetTextProperty(nsIAtom *aProperty,
NS_IMETHOD GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAny, PRBool &aAll); const nsString *aAttribute,
NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty); 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 DeleteSelection(nsIEditor::Direction aDir);
NS_IMETHOD InsertText(const nsString& aStringToInsert); NS_IMETHOD InsertText(const nsString& aStringToInsert);
NS_IMETHOD InsertBreak(); NS_IMETHOD InsertBreak();

Просмотреть файл

@ -28,6 +28,12 @@
#include "nsString.h" #include "nsString.h"
#include "nsIStringStream.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(kIDOMElementIID, NS_IDOMELEMENT_IID);
static NS_DEFINE_IID(kIDOMCharacterDataIID, NS_IDOMCHARACTERDATA_IID); static NS_DEFINE_IID(kIDOMCharacterDataIID, NS_IDOMCHARACTERDATA_IID);
@ -338,12 +344,12 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr
PRBool any = PR_FALSE; PRBool any = PR_FALSE;
PRBool all = PR_FALSE; PRBool all = PR_FALSE;
PRBool first = 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) { if (PR_FALSE==first) {
mEditor->SetTextProperty(nsIEditProperty::i); mEditor->SetTextProperty(nsIEditProperty::i, nsnull, nsnull);
} }
else { 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 any = PR_FALSE;
PRBool all = PR_FALSE; PRBool all = PR_FALSE;
PRBool first = 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) { if (PR_FALSE==first) {
mEditor->SetTextProperty(nsIEditProperty::b); mEditor->SetTextProperty(nsIEditProperty::b, nsnull, nsnull);
} }
else { 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 any = PR_FALSE;
PRBool all = PR_FALSE; PRBool all = PR_FALSE;
PRBool first = 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) { if (PR_FALSE==first) {
mEditor->SetTextProperty(nsIEditProperty::u); mEditor->SetTextProperty(nsIEditProperty::u, nsnull, nsnull);
} }
else { else {
mEditor->RemoveTextProperty(nsIEditProperty::u); mEditor->RemoveTextProperty(nsIEditProperty::u, nsnull);
} }
} }
} }
break; 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; return NS_OK;

Просмотреть файл

@ -49,9 +49,14 @@ public:
NS_IMETHOD Init(nsIDOMDocument *aDoc, nsIPresShell *aPresShell )=0; NS_IMETHOD Init(nsIDOMDocument *aDoc, nsIPresShell *aPresShell )=0;
// Methods shared with nsITextEditor (see nsITextEditor.h for details) // Methods shared with nsITextEditor (see nsITextEditor.h for details)
NS_IMETHOD SetTextProperty(nsIAtom *aProperty)=0; NS_IMETHOD SetTextProperty(nsIAtom *aProperty,
NS_IMETHOD GetTextProperty(nsIAtom *aProperty, PRBool &aFirst, PRBool &aAll, PRBool &aAny)=0; const nsString *aAttribute,
NS_IMETHOD RemoveTextProperty(nsIAtom *aProperty)=0; 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 DeleteSelection(nsIEditor::Direction aDir)=0;
NS_IMETHOD InsertText(const nsString& aStringToInsert)=0; NS_IMETHOD InsertText(const nsString& aStringToInsert)=0;
NS_IMETHOD InsertBreak()=0; NS_IMETHOD InsertBreak()=0;

Просмотреть файл

@ -59,30 +59,46 @@ public:
/** /**
* SetTextProperties() sets the aggregate properties on the current selection * SetTextProperties() sets the aggregate properties on the current selection
* *
* @param aPropList a list of properties to set across the selection * @param aProperty the property to set on the selection
* NOTE: this method is experimental, expect it to change. * @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. * GetTextProperties() gets the aggregate properties of the current selection.
* All object in the current selection are scanned and their attributes are * All object in the current selection are scanned and their attributes are
* represented in a list of Property object. * represented in a list of Property object.
* *
* @param aPropList A list of the various properties that are applied to the text content * @param aProperty the property to get on the selection
* in the current selection. Each item in aPropList is an nsEditProperty. * @param aAttribute the attribute of the property, if applicable. May be null.
* NOTE: this method is experimental, expect it to change. * 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. * RemoveTextProperties() deletes the properties from all text in the current selection.
* If aProperty is not set on the selection, nothing is done. * If aProperty is not set on the selection, nothing is done.
* *
* @param aElement the content element to operate on * @param aProperty the property to reomve from the selection
* @param aAttribute the string representation of the attribute to get * @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. * DeleteSelection removes all nodes in the current selection.

Просмотреть файл

@ -25,6 +25,12 @@
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kITransactionManagerIID, NS_ITRANSACTIONMANAGER_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) nsTransactionManager::nsTransactionManager(PRInt32 aMaxTransactionCount)
: mMaxTransactionCount(aMaxTransactionCount) : mMaxTransactionCount(aMaxTransactionCount)
{ {
@ -229,6 +235,7 @@ nsTransactionManager::Clear()
nsresult nsresult
nsTransactionManager::BeginBatch() nsTransactionManager::BeginBatch()
{ {
if (gNoisy) { printf("Begin Batch\n"); }
nsresult result; nsresult result;
// We can batch independent transactions together by simply pushing // We can batch independent transactions together by simply pushing
@ -248,6 +255,7 @@ nsTransactionManager::BeginBatch()
nsresult nsresult
nsTransactionManager::EndBatch() nsTransactionManager::EndBatch()
{ {
if (gNoisy) { printf("End Batch\n"); }
nsTransactionItem *tx = 0; nsTransactionItem *tx = 0;
nsITransaction *ti = 0; nsITransaction *ti = 0;
nsresult result; nsresult result;