factored out re-parenting of content into MoveContentIntoNewParent

WIP on font handling.
This commit is contained in:
buster%netscape.com 1999-04-16 18:29:12 +00:00
Родитель 0c8a62f098
Коммит 3c2f906370
16 изменённых файлов: 370 добавлений и 143 удалений

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

@ -30,10 +30,10 @@ ChangeAttributeTxn::~ChangeAttributeTxn()
}
NS_IMETHODIMP ChangeAttributeTxn::Init(nsIEditor *aEditor,
nsIDOMElement *aElement,
const nsString& aAttribute,
const nsString& aValue,
PRBool aRemoveAttribute)
nsIDOMElement *aElement,
const nsString& aAttribute,
const nsString& aValue,
PRBool aRemoveAttribute)
{
if (nsnull!=aEditor && nsnull!=aElement)
{

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

@ -20,8 +20,6 @@
#define ChangeAttributeTxn_h__
#include "nsIDOMSelectionListener.h"
#include "nsColor.h"
#include "nsCoord.h"
class TypeInState : public nsIDOMSelectionListener
{
@ -51,19 +49,19 @@ public:
void SetFontFace(nsString aFace);
nsString GetFontFace();
void SetFontColor(nscolor aColor);
nscolor GetFontColor();
void SetFontColor(nsString aColor);
nsString GetFontColor();
void SetFontSize(nscoord aFontSize);
nscoord GetFontSize();
void SetFontSize(nsString aFontSize);
nsString GetFontSize();
protected:
PRBool mBold;
PRBool mItalic;
PRBool mUnderline;
nsString mFontFace;
nscolor mFontColor;
nscoord mFontSize;
nsString mFontColor;
nsString mFontSize;
PRUint32 mIsSet;
};
@ -81,8 +79,6 @@ void TypeInState::Reset()
mBold = PR_FALSE;
mItalic = PR_FALSE;
mUnderline = PR_FALSE;
mFontColor = NS_RGB(0,0,0);
mFontSize = 0;
mIsSet = 0;
};
@ -96,7 +92,10 @@ TypeInState::TypeInState()
inline
PRBool TypeInState::IsSet(PRUint32 aStyle)
{
return (PRBool)(mIsSet & aStyle);
if ((PRBool)(mIsSet & aStyle))
return PR_TRUE;
else
return PR_FALSE;
};
inline
@ -156,25 +155,25 @@ nsString TypeInState::GetFontFace()
{ return mFontFace; };
inline
void TypeInState::SetFontColor(nscolor aColor)
void TypeInState::SetFontColor(nsString aColor)
{
mFontColor = aColor;
mIsSet |= NS_TYPEINSTATE_FONTCOLOR;
};
inline
nscolor TypeInState::GetFontColor()
nsString TypeInState::GetFontColor()
{ return mFontColor; };
inline
void TypeInState::SetFontSize(nscoord aSize)
void TypeInState::SetFontSize(nsString aSize)
{
mFontSize = aSize;
mIsSet |= NS_TYPEINSTATE_FONTSIZE;
};
inline
nscoord TypeInState::GetFontSize()
nsString TypeInState::GetFontSize()
{ return mFontSize; };

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

@ -41,6 +41,11 @@ nsIAtom * nsIEditProperty::sub;
nsIAtom * nsIEditProperty::sup;
nsIAtom * nsIEditProperty::tt;
nsIAtom * nsIEditProperty::u;
// properties
nsIAtom * nsIEditProperty::color;
nsIAtom * nsIEditProperty::face;
nsIAtom * nsIEditProperty::size;
// special
nsString * nsIEditProperty::allProperties;
void
@ -59,6 +64,11 @@ nsEditProperty::InstanceInit()
nsIEditProperty::sup = NS_NewAtom("SUP");
nsIEditProperty::tt = NS_NewAtom("TT");
nsIEditProperty::u = NS_NewAtom("U");
// properties
nsIEditProperty::color= NS_NewAtom("COLOR");
nsIEditProperty::face = NS_NewAtom("FACE");
nsIEditProperty::size = NS_NewAtom("SIZE");
// special
nsIEditProperty::allProperties = new nsString("moz_AllProperties");
}
@ -78,6 +88,11 @@ nsEditProperty::InstanceShutdown()
NS_IF_RELEASE(nsIEditProperty::sup);
NS_IF_RELEASE(nsIEditProperty::tt);
NS_IF_RELEASE(nsIEditProperty::u);
// properties
NS_IF_RELEASE(nsIEditProperty::color);
NS_IF_RELEASE(nsIEditProperty::face);
NS_IF_RELEASE(nsIEditProperty::size);
// special
if (nsIEditProperty::allProperties) {
delete (nsIEditProperty::allProperties);
}

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

@ -428,7 +428,7 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
PRBool first = PR_FALSE;
nsAutoString color = "color";
nsAutoString color = "COLOR";
nsAutoString value = "red";
mEditor->SetTextProperty(nsIEditProperty::font, &color, &value);
}
@ -447,7 +447,7 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
PRBool first = PR_FALSE;
nsAutoString color = "color";
nsAutoString color = "COLOR";
nsAutoString value = "green";
mEditor->SetTextProperty(nsIEditProperty::font, &color, &value);
}

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

@ -71,6 +71,11 @@ SUB places text in subscript style
SUP places text in superscript style
*/
/** properties */
static nsIAtom *color;
static nsIAtom *face;
static nsIAtom *size;
/** special strings */
static nsString *allProperties; // this magic string represents the union of all inline style tags

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

@ -297,10 +297,11 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta
// create style nodes or move it up the content hierarchy as needed.
if ((NS_SUCCEEDED(result)) && newTextNode)
{
nsCOMPtr<nsIDOMNode>newStyleNode;
if (aTypeInState.IsSet(NS_TYPEINSTATE_BOLD))
{
if (PR_TRUE==aTypeInState.GetBold()) {
InsertStyleNode(newTextNode, nsIEditProperty::b, aSelection);
result = InsertStyleNode(newTextNode, nsIEditProperty::b, aSelection, getter_AddRefs(newStyleNode));
}
else {
printf("not yet implemented, make not bold in a bold context\n");
@ -309,7 +310,7 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta
if (aTypeInState.IsSet(NS_TYPEINSTATE_ITALIC))
{
if (PR_TRUE==aTypeInState.GetItalic()) {
InsertStyleNode(newTextNode, nsIEditProperty::i, aSelection);
result = InsertStyleNode(newTextNode, nsIEditProperty::i, aSelection, getter_AddRefs(newStyleNode));
}
else
{
@ -318,14 +319,36 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta
}
if (aTypeInState.IsSet(NS_TYPEINSTATE_UNDERLINE))
{
if (PR_TRUE==aTypeInState.GetUnderline()) {
InsertStyleNode(newTextNode, nsIEditProperty::u, aSelection);
if (PR_TRUE==aTypeInState.GetUnderline()) {
result = InsertStyleNode(newTextNode, nsIEditProperty::u, aSelection, getter_AddRefs(newStyleNode));
}
else
{
printf("not yet implemented, make not underline in an underline context\n");
}
}
if (aTypeInState.IsSet(NS_TYPEINSTATE_FONTCOLOR))
{
nsAutoString fontColor;
fontColor = aTypeInState.GetFontColor();
if (0!=fontColor.Length()) {
result = InsertStyleNode(newTextNode, nsIEditProperty::font, aSelection, getter_AddRefs(newStyleNode));
if (NS_SUCCEEDED(result) && newStyleNode)
{
nsCOMPtr<nsIDOMElement>element = do_QueryInterface(newStyleNode);
if (element)
{
nsAutoString attr;
nsIEditProperty::color->ToString(attr);
result = mEditor->SetAttribute(element, attr, fontColor);
}
}
}
else
{
printf("not yet implemented, make not font in an font context\n");
}
}
}
}
else
@ -374,7 +397,10 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta
}
nsresult
nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode, nsIAtom *aTag, nsIDOMSelection *aSelection)
nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode,
nsIAtom *aTag,
nsIDOMSelection *aSelection,
nsIDOMNode **aNewNode)
{
NS_ASSERTION(aNode && aTag, "bad args");
if (!aNode || !aTag) { return NS_ERROR_NULL_POINTER; }
@ -386,14 +412,13 @@ nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode, nsIAtom *aTag, nsIDOMSelecti
nsIEditorSupport::GetChildOffset(aNode, parent, offsetInParent);
nsAutoString tag;
aTag->ToString(tag);
nsCOMPtr<nsIDOMNode>newStyleNode;
result = mEditor->CreateNode(tag, parent, offsetInParent, getter_AddRefs(newStyleNode));
if ((NS_SUCCEEDED(result)) && newStyleNode)
result = mEditor->CreateNode(tag, parent, offsetInParent, aNewNode);
if ((NS_SUCCEEDED(result)) && *aNewNode)
{
result = mEditor->DeleteNode(aNode);
if (NS_SUCCEEDED(result))
{
result = mEditor->InsertNode(aNode, newStyleNode, 0);
result = mEditor->InsertNode(aNode, *aNewNode, 0);
if (NS_SUCCEEDED(result)) {
if (aSelection) {
aSelection->Collapse(aNode, 0);
@ -424,7 +449,8 @@ nsTextEditRules::InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTa
anchorAsText = do_QueryInterface(anchor);
if (anchorAsText)
{
result = InsertStyleNode(anchor, aTag, aSelection);
nsCOMPtr<nsIDOMNode> newStyleNode;
result = InsertStyleNode(anchor, aTag, aSelection, getter_AddRefs(newStyleNode));
return result;
}
}

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

@ -91,10 +91,13 @@ protected:
/** insert aNode into a new style node of type aTag.
* aSelection is optional. If provided, aSelection is set to (aNode, 0)
* if aNode was successfully placed in a new style node
* @param aNewStyleNode [OUT] The newly created style node, if result is successful
* undefined if result is a failure.
*/
nsresult InsertStyleNode(nsIDOMNode *aNode,
nsIAtom *aTag,
nsIDOMSelection *aSelection);
nsresult InsertStyleNode(nsIDOMNode *aNode,
nsIAtom *aTag,
nsIDOMSelection *aSelection,
nsIDOMNode **aNewStyleNode);
/** create a new style node of type aTag in aParentNode, and put a new text node
* in the new style node.

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

@ -331,7 +331,7 @@ 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, aAttribute);
SetTypeInStateForProperty(mTypeInState, aProperty, aAttribute, aValue);
}
else
{
@ -393,7 +393,7 @@ NS_IMETHODIMP nsTextEditor::SetTextProperty(nsIAtom *aProperty,
{
result = IntermediateNodesAreInline(range, startParent, startOffset,
endParent, endOffset,
startGrandParent, canCollapseStyleNode);
canCollapseStyleNode);
}
if (NS_SUCCEEDED(result))
{
@ -464,6 +464,8 @@ NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty,
result = nsEditor::GetSelection(getter_AddRefs(selection));
if ((NS_SUCCEEDED(result)) && selection)
{
PRBool isCollapsed;
selection->GetIsCollapsed(&isCollapsed);
nsCOMPtr<nsIEnumerator> enumerator;
enumerator = do_QueryInterface(selection);
if (enumerator)
@ -497,7 +499,7 @@ NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty,
if (text)
{
PRBool skipNode = PR_FALSE;
if (PR_TRUE==first && PR_TRUE==firstNodeInRange)
if (PR_FALSE==isCollapsed && PR_TRUE==first && PR_TRUE==firstNodeInRange)
{
firstNodeInRange = PR_FALSE;
PRInt32 startOffset;
@ -540,6 +542,9 @@ NS_IMETHODIMP nsTextEditor::GetTextProperty(nsIAtom *aProperty,
}
}
}
if (PR_FALSE==aAny) { // make sure that if none of the selection is set, we don't report all is set
aAll = PR_FALSE;
}
if (gNoisy) { printf(" returning first=%d any=%d all=%d\n", aFirst, aAny, aAll); }
return result;
}
@ -653,7 +658,7 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty, const nsStrin
if (PR_TRUE==isCollapsed)
{
// manipulating text attributes on a collapsed selection only sets state for the next text insertion
SetTypeInStateForProperty(mTypeInState, aProperty, aAttribute);
SetTypeInStateForProperty(mTypeInState, aProperty, aAttribute, nsnull);
}
else
{
@ -699,7 +704,7 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty, const nsStrin
{
result = IntermediateNodesAreInline(range, startParent, startOffset,
endParent, endOffset,
startGrandParent, canCollapseStyleNode);
canCollapseStyleNode);
}
if (NS_SUCCEEDED(result))
{
@ -713,8 +718,7 @@ NS_IMETHODIMP nsTextEditor::RemoveTextProperty(nsIAtom *aProperty, const nsStrin
}
else
{ // the range is between 2 nodes that have no simple relationship
result = RemoveTextPropertiesForNodeWithDifferentParents(range,
startParent,startOffset,
result = RemoveTextPropertiesForNodeWithDifferentParents(startParent,startOffset,
endParent, endOffset,
commonParent,
aProperty, nsnull);
@ -1126,6 +1130,7 @@ NS_IMETHODIMP nsTextEditor::SetTextPropertiesForNode(nsIDOMNode *aNode,
{
if (gNoisy) { printf("nsTextEditor::SetTextPropertyForNode\n"); }
nsresult result=NS_OK;
// verify that aNode is a text node
nsCOMPtr<nsIDOMCharacterData>nodeAsChar;
nodeAsChar = do_QueryInterface(aNode);
if (!nodeAsChar)
@ -1136,90 +1141,118 @@ NS_IMETHODIMP nsTextEditor::SetTextPropertiesForNode(nsIDOMNode *aNode,
IsTextPropertySetByContent(aNode, aPropName, aAttribute, aValue, textPropertySet, getter_AddRefs(resultNode));
if (PR_FALSE==textPropertySet)
{
PRUint32 count;
nodeAsChar->GetLength(&count);
nsAutoString tag;
aPropName->ToString(tag);
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMNode>newStyleNode;
result = MoveContentIntoNewParent(aNode, aParent, aStartOffset, aEndOffset, tag, getter_AddRefs(newStyleNode));
if (NS_SUCCEEDED(result) && newStyleNode)
{
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);
}
}
}
}
return result;
}
nsCOMPtr<nsIDOMNode>newTextNode; // this will be the text node we move into the new style node
NS_IMETHODIMP nsTextEditor::MoveContentIntoNewParent(nsIDOMNode *aNode,
nsIDOMNode *aOldParentNode,
PRInt32 aStartOffset,
PRInt32 aEndOffset,
nsString aTag,
nsIDOMNode **aNewNode)
{
if (gNoisy) { printf("nsTextEditor::MoveContentIntoNewParent\n"); }
nsresult result=NS_OK;
PRUint32 count;
result = GetLengthOfDOMNode(aNode, count);
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMNode>newChildNode; // this will be the child 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());}
result = nsEditor::SplitNode(aNode, aStartOffset, getter_AddRefs(newChildNode));
if (gNoisy) { printf("* split created left node %p\n", newChildNode.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());}
result = nsEditor::SplitNode(aNode, aEndOffset-aStartOffset, getter_AddRefs(newChildNode));
if (gNoisy) { printf("* split created left node %p\n", newChildNode.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());}
newChildNode = do_QueryInterface(aNode);
if (gNoisy) { printf("* second split not required, new text node set to aNode = %p\n", newChildNode.get());}
}
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))
{
// ??? can we really compute this?
}
*/
if (PR_FALSE==done)
{
nsCOMPtr<nsIDOMCharacterData>newTextNodeAsChar;
newTextNodeAsChar = do_QueryInterface(newTextNode);
PRUint32 newTextNodeLength;
newTextNodeAsChar->GetLength(&newTextNodeLength);
if (0==newTextNodeLength)
// if we've ended up with an empty text node, just delete it and we're done
nsCOMPtr<nsIDOMCharacterData>newChildNodeAsChar;
newChildNodeAsChar = do_QueryInterface(newChildNode);
PRUint32 newChildNodeLength;
if (newChildNodeAsChar)
{
result = nsEditor::DeleteNode(newTextNode);
newChildNodeAsChar->GetLength(&newChildNodeLength);
if (0==newChildNodeLength)
{
result = nsEditor::DeleteNode(newChildNode);
done = PR_TRUE;
}
}
else
// move the new child node into the new parent
if (PR_FALSE==done)
{
nsAutoString tag;
aPropName->ToString(tag);
PRInt32 offsetInParent;
result = nsIEditorSupport::GetChildOffset(aNode, aParent, offsetInParent);
result = nsIEditorSupport::GetChildOffset(aNode, aOldParentNode, offsetInParent);
if (NS_SUCCEEDED(result))
{
nsCOMPtr<nsIDOMNode>newStyleNode;
result = nsEditor::CreateNode(tag, aParent, offsetInParent, getter_AddRefs(newStyleNode));
if (NS_SUCCEEDED(result) && newStyleNode)
result = nsEditor::CreateNode(aTag, aOldParentNode, offsetInParent, aNewNode);
if (NS_SUCCEEDED(result) && *aNewNode)
{
if (gNoisy) { printf("* created new style node %p\n", newStyleNode.get());}
if (gNoisy) { printf("* created new style node %p\n", *aNewNode);}
if (gNoisy) {DebugDumpContent(); } // DEBUG
if (aAttribute)
result = nsEditor::DeleteNode(newChildNode);
if (NS_SUCCEEDED(result))
{
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);
result = nsEditor::InsertNode(newChildNode, *aNewNode, 0);
if (NS_SUCCEEDED(result))
{
result = nsEditor::InsertNode(newTextNode, newStyleNode, 0);
{ // set the selection
nsCOMPtr<nsIDOMSelection>selection;
result = nsEditor::GetSelection(getter_AddRefs(selection));
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);
}
{
selection->Collapse(newChildNode, 0);
PRInt32 endOffset = aEndOffset-aStartOffset;
selection->Extend(newChildNode, endOffset);
}
}
}
@ -1233,6 +1266,34 @@ NS_IMETHODIMP nsTextEditor::SetTextPropertiesForNode(nsIDOMNode *aNode,
return result;
}
// returns the number of things inside aNode.
// If aNode is text, returns number of characters. If not, returns number of children nodes.
NS_IMETHODIMP nsTextEditor::GetLengthOfDOMNode(nsIDOMNode *aNode, PRUint32 &aCount) const
{
aCount = 0;
if (!aNode) { return NS_ERROR_NULL_POINTER; }
nsresult result=NS_OK;
nsCOMPtr<nsIDOMCharacterData>nodeAsChar;
nodeAsChar = do_QueryInterface(aNode);
if (nodeAsChar) {
nodeAsChar->GetLength(&aCount);
}
else
{
PRBool hasChildNodes;
aNode->HasChildNodes(&hasChildNodes);
if (PR_TRUE==hasChildNodes)
{
nsCOMPtr<nsIDOMNodeList>nodeList;
result = aNode->GetChildNodes(getter_AddRefs(nodeList));
if (NS_SUCCEEDED(result) && nodeList) {
nodeList->GetLength(&aCount);
}
}
}
return result;
}
// content-based inline vs. block query
NS_IMETHODIMP nsTextEditor::IsNodeInline(nsIDOMNode *aNode, PRBool &aIsInline) const
{
@ -1277,11 +1338,10 @@ nsTextEditor::IntermediateNodesAreInline(nsIDOMRange *aRange,
PRInt32 aStartOffset,
nsIDOMNode *aEndNode,
PRInt32 aEndOffset,
nsIDOMNode *aParent,
PRBool &aResult) const
{
aResult = PR_TRUE; // init out param. we assume the condition is true unless we find a node that violates it
if (!aStartNode || !aEndNode || !aParent) { return NS_ERROR_NULL_POINTER; }
if (!aStartNode || !aEndNode || !aRange) { return NS_ERROR_NULL_POINTER; }
nsCOMPtr<nsIContentIterator>iter;
nsresult result;
@ -1852,8 +1912,7 @@ nsTextEditor::RemoveTextPropertiesForNodesWithSameParent(nsIDOMNode *aStartNode,
}
NS_IMETHODIMP
nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange,
nsIDOMNode *aStartNode,
nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStartNode,
PRInt32 aStartOffset,
nsIDOMNode *aEndNode,
PRInt32 aEndOffset,
@ -1863,7 +1922,7 @@ nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRang
{
if (gNoisy) { printf("nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents\n"); }
nsresult result=NS_OK;
if (!aRange || !aStartNode || !aEndNode || !aParent || !aPropName)
if (!aStartNode || !aEndNode || !aParent || !aPropName)
return NS_ERROR_NULL_POINTER;
PRInt32 rangeStartOffset = aStartOffset; // used to construct a range for the nodes between
@ -2041,7 +2100,8 @@ nsTextEditor::RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRang
NS_IMETHODIMP
nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState,
nsIAtom *aPropName,
const nsString *aAttribute)
const nsString *aAttribute,
const nsString *aValue)
{
if (!aPropName) {
return NS_ERROR_NULL_POINTER;
@ -2068,7 +2128,7 @@ nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState,
aTypeInState.UnSet(NS_TYPEINSTATE_ITALIC);
}
else
{ // get the current style and set boldness to the opposite of the current state
{ // get the current style and set italic proper to the opposite of the current state
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
PRBool first = PR_FALSE;
@ -2076,14 +2136,14 @@ nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState,
aTypeInState.SetItalic(!any);
}
}
else if (nsIEditProperty::u==aPropName)
else if (nsIEditProperty::u==aPropName)
{
if (PR_TRUE==aTypeInState.IsSet(NS_TYPEINSTATE_UNDERLINE))
{ // toggle currently set italicness
aTypeInState.UnSet(NS_TYPEINSTATE_UNDERLINE);
}
else
{ // get the current style and set boldness to the opposite of the current state
{ // get the current style and set underline prop to the opposite of the current state
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
PRBool first = PR_FALSE;
@ -2091,8 +2151,42 @@ nsTextEditor::SetTypeInStateForProperty(TypeInState &aTypeInState,
aTypeInState.SetUnderline(!any);
}
}
else {
return NS_ERROR_FAILURE;
else if (nsIEditProperty::font==aPropName)
{
if (!aAttribute) { return NS_ERROR_NULL_POINTER; }
nsIAtom *attribute = NS_NewAtom(*aAttribute);
if (!attribute) { return NS_ERROR_NULL_POINTER; }
if (nsIEditProperty::color==attribute)
{
if (PR_TRUE==aTypeInState.IsSet(NS_TYPEINSTATE_FONTCOLOR))
{
if (nsnull==aValue) {
aTypeInState.UnSet(NS_TYPEINSTATE_FONTCOLOR);
}
else { // we're just changing the value of color
aTypeInState.SetFontColor(*aValue);
}
}
else
{ // get the current style and set font color if it's needed
if (!aValue) { return NS_ERROR_NULL_POINTER; }
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
PRBool first = PR_FALSE;
GetTextProperty(aPropName, aAttribute, aValue, first, any, all); // operates on current selection
if (PR_FALSE==all) {
aTypeInState.SetFontColor(*aValue);
}
}
}
else if (nsIEditProperty::face==attribute)
{
}
if (nsIEditProperty::size==attribute)
{
}
else { return NS_ERROR_FAILURE; }
}
else { return NS_ERROR_FAILURE; }
return NS_OK;
}

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

@ -103,28 +103,67 @@ protected:
// Utility Methods
virtual void IsTextPropertySetByContent(nsIDOMNode *aNode,
nsIAtom *aProperty,
/** content-based query returns PR_TRUE if <aProperty aAttribute=aValue> effects aNode
* If <aProperty aAttribute=aValue> contains aNode,
* but <aProperty aAttribute=SomeOtherValue> also contains aNode and the second is
* more deeply nested than the first, then the first does not effect aNode.
*
* @param aNode The target of the query
* @param aProperty The property that we are querying for
* @param aAttribute The attribute of aProperty, example: color in <FONT color="blue">
* May be null.
* @param aValue The value of aAttribute, example: blue in <FONT color="blue">
* May be null. Ignored if aAttribute is null.
* @param aIsSet [OUT] PR_TRUE if <aProperty aAttribute=aValue> effects aNode.
* @param aStyleNode [OUT] set to the node representing <aProperty aAttribute=aValue>, if found.
* null if aIsSet is returned as PR_FALSE;
*/
virtual void IsTextPropertySetByContent(nsIDOMNode *aNode,
nsIAtom *aProperty,
const nsString *aAttribute,
const nsString *aValue,
PRBool &aIsSet,
nsIDOMNode **aStyleNode) const;
PRBool &aIsSet,
nsIDOMNode **aStyleNode) const;
/** style-based query returns PR_TRUE if (aProperty, aAttribute) is set in aSC.
* WARNING: not well tested yet since we don't do style-based queries anywhere.
*/
virtual void IsTextStyleSet(nsIStyleContext *aSC,
nsIAtom *aProperty,
const nsString *aAttributes,
PRBool &aIsSet) const;
/** returns PR_TRUE in out-param aIsInline if aNode is inline as defined by HTML DTD */
NS_IMETHOD IsNodeInline(nsIDOMNode *aNode, PRBool &aIsInline) const;
/** returns PR_TRUE in out-param aResult if all nodes between (aStartNode, aStartOffset)
* and (aEndNode, aEndOffset) are inline as defined by HTML DTD.
*/
NS_IMETHOD IntermediateNodesAreInline(nsIDOMRange *aRange,
nsIDOMNode *aStartNode,
PRInt32 aStartOffset,
nsIDOMNode *aEndNode,
PRInt32 aEndOffset,
nsIDOMNode *aParent,
PRBool &aResult) const;
/** returns the number of things inside aNode in the out-param aCount.
* If aNode is text, returns number of characters.
* If not, returns number of children nodes.
*/
NS_IMETHOD GetLengthOfDOMNode(nsIDOMNode *aNode, PRUint32 &aCount) const;
/** Moves the content between (aNode, aStartOffset) and (aNode, aEndOffset)
* into aNewParentNode, splitting aNode as necessary to maintain the relative
* position of all leaf content.
*/
NS_IMETHOD nsTextEditor::MoveContentIntoNewParent(nsIDOMNode *aNode,
nsIDOMNode *aOldParentNode,
PRInt32 aStartOffset,
PRInt32 aEndOffset,
nsString aTag,
nsIDOMNode **aNewNode);
NS_IMETHOD SetTextPropertiesForNode(nsIDOMNode *aNode,
nsIDOMNode *aParent,
PRInt32 aStartOffset,
@ -167,8 +206,7 @@ protected:
nsIAtom *aPropName,
const nsString *aAttribute);
NS_IMETHOD RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMRange *aRange,
nsIDOMNode *aStartNode,
NS_IMETHOD RemoveTextPropertiesForNodeWithDifferentParents(nsIDOMNode *aStartNode,
PRInt32 aStartOffset,
nsIDOMNode *aEndNode,
PRInt32 aEndOffset,
@ -176,11 +214,10 @@ protected:
nsIAtom *aPropName,
const nsString *aAttribute);
NS_IMETHOD SetTypeInStateForProperty(TypeInState &aTypeInState,
nsIAtom *aPropName,
const nsString *aAttribute);
const nsString *aAttribute,
const nsString *aValue);
TypeInState GetTypeInState() { return mTypeInState;}

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

@ -30,10 +30,10 @@ ChangeAttributeTxn::~ChangeAttributeTxn()
}
NS_IMETHODIMP ChangeAttributeTxn::Init(nsIEditor *aEditor,
nsIDOMElement *aElement,
const nsString& aAttribute,
const nsString& aValue,
PRBool aRemoveAttribute)
nsIDOMElement *aElement,
const nsString& aAttribute,
const nsString& aValue,
PRBool aRemoveAttribute)
{
if (nsnull!=aEditor && nsnull!=aElement)
{

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

@ -71,6 +71,11 @@ SUB places text in subscript style
SUP places text in superscript style
*/
/** properties */
static nsIAtom *color;
static nsIAtom *face;
static nsIAtom *size;
/** special strings */
static nsString *allProperties; // this magic string represents the union of all inline style tags

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

@ -20,8 +20,6 @@
#define ChangeAttributeTxn_h__
#include "nsIDOMSelectionListener.h"
#include "nsColor.h"
#include "nsCoord.h"
class TypeInState : public nsIDOMSelectionListener
{
@ -51,19 +49,19 @@ public:
void SetFontFace(nsString aFace);
nsString GetFontFace();
void SetFontColor(nscolor aColor);
nscolor GetFontColor();
void SetFontColor(nsString aColor);
nsString GetFontColor();
void SetFontSize(nscoord aFontSize);
nscoord GetFontSize();
void SetFontSize(nsString aFontSize);
nsString GetFontSize();
protected:
PRBool mBold;
PRBool mItalic;
PRBool mUnderline;
nsString mFontFace;
nscolor mFontColor;
nscoord mFontSize;
nsString mFontColor;
nsString mFontSize;
PRUint32 mIsSet;
};
@ -81,8 +79,6 @@ void TypeInState::Reset()
mBold = PR_FALSE;
mItalic = PR_FALSE;
mUnderline = PR_FALSE;
mFontColor = NS_RGB(0,0,0);
mFontSize = 0;
mIsSet = 0;
};
@ -96,7 +92,10 @@ TypeInState::TypeInState()
inline
PRBool TypeInState::IsSet(PRUint32 aStyle)
{
return (PRBool)(mIsSet & aStyle);
if ((PRBool)(mIsSet & aStyle))
return PR_TRUE;
else
return PR_FALSE;
};
inline
@ -156,25 +155,25 @@ nsString TypeInState::GetFontFace()
{ return mFontFace; };
inline
void TypeInState::SetFontColor(nscolor aColor)
void TypeInState::SetFontColor(nsString aColor)
{
mFontColor = aColor;
mIsSet |= NS_TYPEINSTATE_FONTCOLOR;
};
inline
nscolor TypeInState::GetFontColor()
nsString TypeInState::GetFontColor()
{ return mFontColor; };
inline
void TypeInState::SetFontSize(nscoord aSize)
void TypeInState::SetFontSize(nsString aSize)
{
mFontSize = aSize;
mIsSet |= NS_TYPEINSTATE_FONTSIZE;
};
inline
nscoord TypeInState::GetFontSize()
nsString TypeInState::GetFontSize()
{ return mFontSize; };

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

@ -41,6 +41,11 @@ nsIAtom * nsIEditProperty::sub;
nsIAtom * nsIEditProperty::sup;
nsIAtom * nsIEditProperty::tt;
nsIAtom * nsIEditProperty::u;
// properties
nsIAtom * nsIEditProperty::color;
nsIAtom * nsIEditProperty::face;
nsIAtom * nsIEditProperty::size;
// special
nsString * nsIEditProperty::allProperties;
void
@ -59,6 +64,11 @@ nsEditProperty::InstanceInit()
nsIEditProperty::sup = NS_NewAtom("SUP");
nsIEditProperty::tt = NS_NewAtom("TT");
nsIEditProperty::u = NS_NewAtom("U");
// properties
nsIEditProperty::color= NS_NewAtom("COLOR");
nsIEditProperty::face = NS_NewAtom("FACE");
nsIEditProperty::size = NS_NewAtom("SIZE");
// special
nsIEditProperty::allProperties = new nsString("moz_AllProperties");
}
@ -78,6 +88,11 @@ nsEditProperty::InstanceShutdown()
NS_IF_RELEASE(nsIEditProperty::sup);
NS_IF_RELEASE(nsIEditProperty::tt);
NS_IF_RELEASE(nsIEditProperty::u);
// properties
NS_IF_RELEASE(nsIEditProperty::color);
NS_IF_RELEASE(nsIEditProperty::face);
NS_IF_RELEASE(nsIEditProperty::size);
// special
if (nsIEditProperty::allProperties) {
delete (nsIEditProperty::allProperties);
}

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

@ -428,7 +428,7 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
PRBool first = PR_FALSE;
nsAutoString color = "color";
nsAutoString color = "COLOR";
nsAutoString value = "red";
mEditor->SetTextProperty(nsIEditProperty::font, &color, &value);
}
@ -447,7 +447,7 @@ nsTextEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aPr
PRBool any = PR_FALSE;
PRBool all = PR_FALSE;
PRBool first = PR_FALSE;
nsAutoString color = "color";
nsAutoString color = "COLOR";
nsAutoString value = "green";
mEditor->SetTextProperty(nsIEditProperty::font, &color, &value);
}

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

@ -297,10 +297,11 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta
// create style nodes or move it up the content hierarchy as needed.
if ((NS_SUCCEEDED(result)) && newTextNode)
{
nsCOMPtr<nsIDOMNode>newStyleNode;
if (aTypeInState.IsSet(NS_TYPEINSTATE_BOLD))
{
if (PR_TRUE==aTypeInState.GetBold()) {
InsertStyleNode(newTextNode, nsIEditProperty::b, aSelection);
result = InsertStyleNode(newTextNode, nsIEditProperty::b, aSelection, getter_AddRefs(newStyleNode));
}
else {
printf("not yet implemented, make not bold in a bold context\n");
@ -309,7 +310,7 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta
if (aTypeInState.IsSet(NS_TYPEINSTATE_ITALIC))
{
if (PR_TRUE==aTypeInState.GetItalic()) {
InsertStyleNode(newTextNode, nsIEditProperty::i, aSelection);
result = InsertStyleNode(newTextNode, nsIEditProperty::i, aSelection, getter_AddRefs(newStyleNode));
}
else
{
@ -318,14 +319,36 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta
}
if (aTypeInState.IsSet(NS_TYPEINSTATE_UNDERLINE))
{
if (PR_TRUE==aTypeInState.GetUnderline()) {
InsertStyleNode(newTextNode, nsIEditProperty::u, aSelection);
if (PR_TRUE==aTypeInState.GetUnderline()) {
result = InsertStyleNode(newTextNode, nsIEditProperty::u, aSelection, getter_AddRefs(newStyleNode));
}
else
{
printf("not yet implemented, make not underline in an underline context\n");
}
}
if (aTypeInState.IsSet(NS_TYPEINSTATE_FONTCOLOR))
{
nsAutoString fontColor;
fontColor = aTypeInState.GetFontColor();
if (0!=fontColor.Length()) {
result = InsertStyleNode(newTextNode, nsIEditProperty::font, aSelection, getter_AddRefs(newStyleNode));
if (NS_SUCCEEDED(result) && newStyleNode)
{
nsCOMPtr<nsIDOMElement>element = do_QueryInterface(newStyleNode);
if (element)
{
nsAutoString attr;
nsIEditProperty::color->ToString(attr);
result = mEditor->SetAttribute(element, attr, fontColor);
}
}
}
else
{
printf("not yet implemented, make not font in an font context\n");
}
}
}
}
else
@ -374,7 +397,10 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta
}
nsresult
nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode, nsIAtom *aTag, nsIDOMSelection *aSelection)
nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode,
nsIAtom *aTag,
nsIDOMSelection *aSelection,
nsIDOMNode **aNewNode)
{
NS_ASSERTION(aNode && aTag, "bad args");
if (!aNode || !aTag) { return NS_ERROR_NULL_POINTER; }
@ -386,14 +412,13 @@ nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode, nsIAtom *aTag, nsIDOMSelecti
nsIEditorSupport::GetChildOffset(aNode, parent, offsetInParent);
nsAutoString tag;
aTag->ToString(tag);
nsCOMPtr<nsIDOMNode>newStyleNode;
result = mEditor->CreateNode(tag, parent, offsetInParent, getter_AddRefs(newStyleNode));
if ((NS_SUCCEEDED(result)) && newStyleNode)
result = mEditor->CreateNode(tag, parent, offsetInParent, aNewNode);
if ((NS_SUCCEEDED(result)) && *aNewNode)
{
result = mEditor->DeleteNode(aNode);
if (NS_SUCCEEDED(result))
{
result = mEditor->InsertNode(aNode, newStyleNode, 0);
result = mEditor->InsertNode(aNode, *aNewNode, 0);
if (NS_SUCCEEDED(result)) {
if (aSelection) {
aSelection->Collapse(aNode, 0);
@ -424,7 +449,8 @@ nsTextEditRules::InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTa
anchorAsText = do_QueryInterface(anchor);
if (anchorAsText)
{
result = InsertStyleNode(anchor, aTag, aSelection);
nsCOMPtr<nsIDOMNode> newStyleNode;
result = InsertStyleNode(anchor, aTag, aSelection, getter_AddRefs(newStyleNode));
return result;
}
}

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

@ -91,10 +91,13 @@ protected:
/** insert aNode into a new style node of type aTag.
* aSelection is optional. If provided, aSelection is set to (aNode, 0)
* if aNode was successfully placed in a new style node
* @param aNewStyleNode [OUT] The newly created style node, if result is successful
* undefined if result is a failure.
*/
nsresult InsertStyleNode(nsIDOMNode *aNode,
nsIAtom *aTag,
nsIDOMSelection *aSelection);
nsresult InsertStyleNode(nsIDOMNode *aNode,
nsIAtom *aTag,
nsIDOMSelection *aSelection,
nsIDOMNode **aNewStyleNode);
/** create a new style node of type aTag in aParentNode, and put a new text node
* in the new style node.