bug 140357: (html editor) deletion should preserve style state. r=brade; sr=kin

This commit is contained in:
jfrancis%netscape.com 2003-06-02 22:21:06 +00:00
Родитель ba44a2b994
Коммит f3491fa767
8 изменённых файлов: 375 добавлений и 21 удалений

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

@ -68,6 +68,42 @@ interface nsIHTMLEditor : nsISupports
/* ------------ Inline property methods -------------- */
/**
* AddDefaultProperty() registers a default style property with the editor
*
* @param aProperty the property to set by default
* @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.
* Example: aProperty="font", aAttribute="color",
* aValue="0x00FFFF"
*/
void addDefaultProperty(in nsIAtom aProperty,
in AString aAttribute,
in AString aValue);
/**
* RemoveDefaultProperty() unregisters a default style property with the editor
*
* @param aProperty the property to remove from defaults
* @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.
* Example: aProperty="font", aAttribute="color",
* aValue="0x00FFFF"
*/
void removeDefaultProperty(in nsIAtom aProperty,
in AString aAttribute,
in AString aValue);
/**
* RemoveAllDefaultProperties() unregisters all default style properties with the editor
*
*/
void removeAllDefaultProperties();
/**
* SetInlineProperty() sets the aggregate properties on the current selection
*

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

@ -76,6 +76,7 @@ TypeInState::TypeInState() :
,mClearedArray()
,mRelativeFontSize(0)
,mLastSelectionOffset(0)
,mIgnoreSelNotificationHACK(PR_FALSE)
{
Reset();
}
@ -100,6 +101,14 @@ NS_IMETHODIMP TypeInState::NotifySelectionChanged(nsIDOMDocument *, nsISelection
// XXX: This code temporarily fixes the problem where clicking the mouse in
// XXX: the same location clears the type-in-state.
if (mIgnoreSelNotificationHACK)
{
// short circuit the notification if editor has warned us that bogus
// notification is coming.
mIgnoreSelNotificationHACK = PR_FALSE;
return NS_OK;
}
if (aSelection)
{
PRBool isCollapsed = PR_FALSE;
@ -428,8 +437,8 @@ PRBool TypeInState::IsPropCleared(nsIAtom *aProp,
}
PRBool TypeInState::FindPropInList(nsIAtom *aProp,
const nsString &aAttr,
nsString *outValue,
const nsAString &aAttr,
nsAString *outValue,
nsVoidArray &aList,
PRInt32 &outIndex)
{
@ -455,7 +464,7 @@ PRBool TypeInState::FindPropInList(nsIAtom *aProp,
* PropItem: helper struct for TypeInState
*******************************************************************/
PropItem::PropItem(nsIAtom *aTag, const nsString &aAttr, const nsString &aValue) :
PropItem::PropItem(nsIAtom *aTag, const nsAString &aAttr, const nsAString &aValue) :
tag(aTag)
,attr(aAttr)
,value(aValue)

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

@ -53,7 +53,8 @@ struct PropItem
nsString attr;
nsString value;
PropItem(nsIAtom *aTag, const nsString &aAttr, const nsString &aValue);
PropItem() : tag(nsnull), attr(), value() {};
PropItem(nsIAtom *aTag, const nsAString &aAttr, const nsAString &aValue);
~PropItem();
};
@ -98,6 +99,8 @@ public:
nsresult GetTypingState(PRBool &isSet, PRBool &theSetting, nsIAtom *aProp,
const nsString &aAttr, nsString* outValue);
static PRBool FindPropInList(nsIAtom *aProp, const nsAString &aAttr, nsAString *outValue, nsVoidArray &aList, PRInt32 &outIndex);
protected:
nsresult RemovePropFromSetList(nsIAtom *aProp, const nsString &aAttr);
@ -106,13 +109,15 @@ protected:
PRBool IsPropSet(nsIAtom *aProp, const nsString &aAttr, nsString* outValue, PRInt32 &outIndex);
PRBool IsPropCleared(nsIAtom *aProp, const nsString &aAttr);
PRBool IsPropCleared(nsIAtom *aProp, const nsString &aAttr, PRInt32 &outIndex);
PRBool FindPropInList(nsIAtom *aProp, const nsString &aAttr, nsString *outValue, nsVoidArray &aList, PRInt32 &outIndex);
nsVoidArray mSetArray;
nsVoidArray mClearedArray;
PRInt32 mRelativeFontSize;
nsCOMPtr<nsIDOMNode> mLastSelectionContainer;
PRInt32 mLastSelectionOffset;
PRBool mIgnoreSelNotificationHACK;
friend class nsHTMLEditRules;
};

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

@ -49,7 +49,6 @@
#include "nsTextEditUtils.h"
#include "nsHTMLEditUtils.h"
#include "nsHTMLEditor.h"
#include "TypeInState.h"
#include "nsIServiceManager.h"
#include "nsCRT.h"
@ -191,10 +190,31 @@ nsHTMLEditRules::nsHTMLEditRules() :
mDocChangeRange(nsnull)
,mListenerEnabled(PR_TRUE)
,mReturnInEmptyLIKillsList(PR_TRUE)
,mDidDeleteSelection(PR_FALSE)
,mDidRangedDelete(PR_FALSE)
,mUtilRange(nsnull)
,mJoinOffset(0)
{
// populate mCachedStyles
mCachedStyles[0] = StyleCache(nsEditProperty::b, nsString(), nsString());
mCachedStyles[1] = StyleCache(nsEditProperty::i, nsString(), nsString());
mCachedStyles[2] = StyleCache(nsEditProperty::u, nsString(), nsString());
mCachedStyles[3] = StyleCache(nsEditProperty::font, NS_LITERAL_STRING("face"), nsString());
mCachedStyles[4] = StyleCache(nsEditProperty::font, NS_LITERAL_STRING("size"), nsString());
mCachedStyles[5] = StyleCache(nsEditProperty::font, NS_LITERAL_STRING("color"), nsString());
mCachedStyles[6] = StyleCache(nsEditProperty::tt, nsString(), nsString());
mCachedStyles[7] = StyleCache(nsEditProperty::em, nsString(), nsString());
mCachedStyles[8] = StyleCache(nsEditProperty::strong, nsString(), nsString());
mCachedStyles[9] = StyleCache(nsEditProperty::dfn, nsString(), nsString());
mCachedStyles[10] = StyleCache(nsEditProperty::code, nsString(), nsString());
mCachedStyles[11] = StyleCache(nsEditProperty::samp, nsString(), nsString());
mCachedStyles[12] = StyleCache(nsEditProperty::var, nsString(), nsString());
mCachedStyles[13] = StyleCache(nsEditProperty::cite, nsString(), nsString());
mCachedStyles[14] = StyleCache(nsEditProperty::abbr, nsString(), nsString());
mCachedStyles[15] = StyleCache(nsEditProperty::acronym, nsString(), nsString());
mCachedStyles[16] = StyleCache(nsEditProperty::cssBackgroundColor, nsString(), nsString());
mCachedStyles[17] = StyleCache(nsEditProperty::sub, nsString(), nsString());
mCachedStyles[18] = StyleCache(nsEditProperty::sup, nsString(), nsString());
}
nsHTMLEditRules::~nsHTMLEditRules()
@ -302,22 +322,44 @@ nsHTMLEditRules::BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection)
if (NS_FAILED(res)) return res;
// get the selection start location
nsCOMPtr<nsIDOMNode> selNode;
nsCOMPtr<nsIDOMNode> selStartNode, selEndNode;
PRInt32 selOffset;
res = mHTMLEditor->GetStartNodeAndOffset(selection, address_of(selNode), &selOffset);
res = mHTMLEditor->GetStartNodeAndOffset(selection, address_of(selStartNode), &selOffset);
if (NS_FAILED(res)) return res;
mRangeItem.startNode = selNode;
mRangeItem.startNode = selStartNode;
mRangeItem.startOffset = selOffset;
// get the selection end location
res = mHTMLEditor->GetEndNodeAndOffset(selection, address_of(selNode), &selOffset);
res = mHTMLEditor->GetEndNodeAndOffset(selection, address_of(selEndNode), &selOffset);
if (NS_FAILED(res)) return res;
mRangeItem.endNode = selNode;
mRangeItem.endNode = selEndNode;
mRangeItem.endOffset = selOffset;
// register this range with range updater to track this as we perturb the doc
(mHTMLEditor->mRangeUpdater).RegisterRangeItem(&mRangeItem);
// clear deletion state bool
mDidDeleteSelection = PR_FALSE;
// HACK: all sorts of hurt for managing typeinstate. If we are deleting,
// or doing a block operation, clear the type in state
if ((action == nsEditor::kOpDeleteText) ||
(action == nsEditor::kOpDeleteSelection) ||
(action == nsHTMLEditor::kOpMakeList) ||
(action == nsHTMLEditor::kOpIndent) ||
(action == nsHTMLEditor::kOpOutdent) ||
(action == nsHTMLEditor::kOpAlign) ||
(action == nsHTMLEditor::kOpMakeBasicBlock) ||
(action == nsHTMLEditor::kOpRemoveList) ||
(action == nsHTMLEditor::kOpMakeDefListItem) ||
(action == nsHTMLEditor::kOpInsertElement) ||
(action == nsHTMLEditor::kOpInsertQuotation) ||
(action == nsHTMLEditor::kOpInsertBreak) ||
(action == nsHTMLEditor::kOpInsertBreak))
{
mHTMLEditor->mTypeInState->Reset();
}
// clear out mDocChangeRange and mUtilRange
nsCOMPtr<nsIDOMNSRange> nsrange;
if(mDocChangeRange)
@ -334,6 +376,19 @@ nsHTMLEditRules::BeforeEdit(PRInt32 action, nsIEditor::EDirection aDirection)
return NS_ERROR_FAILURE;
nsrange->NSDetach(); // ditto for mUtilRange.
}
// remember current inline styles for deletion and normal insertion operations
if ((action == nsEditor::kOpInsertText) ||
(action == nsEditor::kOpInsertIMEText) ||
(action == nsEditor::kOpDeleteSelection) ||
(action == nsEditor::kOpInsertBreak))
{
nsCOMPtr<nsIDOMNode> selNode = selStartNode;
if (aDirection == nsIEditor::eNext)
selNode = selEndNode;
res = CacheInlineStyles(selNode);
if (NS_FAILED(res)) return res;
}
// check that selection is in subtree defined by body node
ConfirmSelectionInBody();
@ -446,13 +501,14 @@ nsHTMLEditRules::AfterEditInner(PRInt32 action, nsIEditor::EDirection aDirection
(action == nsHTMLEditor::kOpLoadHTML)))
{
res = ReplaceNewlines(mDocChangeRange);
if (NS_FAILED(res)) return res;
}
// clean up any empty nodes in the selection
res = RemoveEmptyNodes();
if (NS_FAILED(res)) return res;
// attempt to transform any uneeded nbsp's into spaces after doing various operations
// attempt to transform any unneeded nbsp's into spaces after doing various operations
if ((action == nsEditor::kOpInsertText) ||
(action == nsEditor::kOpInsertIMEText) ||
(action == nsEditor::kOpDeleteSelection) ||
@ -490,7 +546,19 @@ nsHTMLEditRules::AfterEditInner(PRInt32 action, nsIEditor::EDirection aDirection
res = AdjustSelection(selection, aDirection);
if (NS_FAILED(res)) return res;
}
// check for any styles which were removed inappropriately
if ((action == nsEditor::kOpInsertText) ||
(action == nsEditor::kOpInsertIMEText) ||
(action == nsEditor::kOpDeleteSelection) ||
(action == nsEditor::kOpInsertBreak))
{
mHTMLEditor->mTypeInState->mIgnoreSelNotificationHACK = PR_TRUE;
res = ReapplyCachedStyles();
if (NS_FAILED(res)) return res;
res = ClearCachedStyles();
if (NS_FAILED(res)) return res;
}
}
// detect empty doc
@ -1788,6 +1856,9 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
// remember that we did a selection deletion. Used by CreateStyleForInsertText()
mDidDeleteSelection = PR_TRUE;
// if there is only bogus content, cancel the operation
if (mBogusNode)
{
@ -4044,6 +4115,48 @@ nsHTMLEditRules::CreateStyleForInsertText(nsISelection *aSelection, nsIDOMDocume
if (NS_FAILED(res)) return res;
PropItem *item = nsnull;
// if we deleted selection then also for cached styles
if (mDidDeleteSelection &&
((mTheAction == nsEditor::kOpInsertText ) ||
(mTheAction == nsEditor::kOpInsertIMEText) ||
(mTheAction == nsEditor::kOpInsertBreak) ||
(mTheAction == nsEditor::kOpDeleteSelection)))
{
res = ReapplyCachedStyles();
if (NS_FAILED(res)) return res;
}
// either way we clear the cached styles array
res = ClearCachedStyles();
if (NS_FAILED(res)) return res;
// next examine our present style and make sure default styles are either present or
// explicitly overridden. If neither, add the default style to the TypeInState
PRInt32 j, defcon = mHTMLEditor->mDefaultStyles.Count();
for (j=0; j<defcon; j++)
{
PropItem *propItem = (PropItem*)mHTMLEditor->mDefaultStyles[j];
if (!propItem)
return NS_ERROR_NULL_POINTER;
PRBool bFirst, bAny, bAll;
// GetInlineProperty also examine TypeInState. The only gotcha here is that a cleared
// property looks like an unset property. For now I'm assuming that's not a problem:
// that default styles will always be multivalue styles (like font face or size) where
// clearing the style means we want to go back to the default. If we ever wanted a
// "toggle" style like bold for a default, though, I'll have to add code to detect the
// difference between unset and explicitly cleared, else user would never be able to
// unbold, for instance.
nsAutoString curValue;
res = mHTMLEditor->GetInlinePropertyBase(propItem->tag, &(propItem->attr), nsnull,
&bFirst, &bAny, &bAll, &curValue, PR_FALSE);
if (NS_FAILED(res)) return res;
if (!bAny) // no style set for this prop/attr
{
mHTMLEditor->mTypeInState->SetProp(propItem->tag, propItem->attr, propItem->value);
}
}
// process clearing any styles first
mHTMLEditor->mTypeInState->TakeClearProperty(&item);
while (item)
@ -6939,6 +7052,74 @@ nsHTMLEditRules::GetTopEnclosingMailCite(nsIDOMNode *aNode,
}
nsresult
nsHTMLEditRules::CacheInlineStyles(nsIDOMNode *aNode)
{
if (!aNode) return NS_ERROR_NULL_POINTER;
PRInt32 j;
for (j=0; j<SIZE_STYLE_TABLE; j++)
{
PRBool isSet = PR_FALSE;
nsAutoString outValue;
nsCOMPtr<nsIDOMNode> resultNode;
mHTMLEditor->IsTextPropertySetByContent(aNode, mCachedStyles[j].tag, &(mCachedStyles[j].attr), nsnull,
isSet, getter_AddRefs(resultNode), &outValue);
if (isSet)
{
mCachedStyles[j].mPresent = PR_TRUE;
mCachedStyles[j].value.Assign(outValue);
}
}
return NS_OK;
}
nsresult
nsHTMLEditRules::ReapplyCachedStyles()
{
// The idea here is to examine our cached list of styles
// and see if any have been removed. If so, add typeinstate
// for them, so that they will be reinserted when new
// content is added.
nsresult res = NS_OK;
PRInt32 j;
for (j=0; j<SIZE_STYLE_TABLE; j++)
{
if (mCachedStyles[j].mPresent)
{
PRBool bFirst, bAny, bAll;
nsAutoString curValue;
res = mHTMLEditor->GetInlinePropertyBase(mCachedStyles[j].tag, &(mCachedStyles[j].attr), &(mCachedStyles[j].value),
&bFirst, &bAny, &bAll, &curValue, PR_FALSE);
if (NS_FAILED(res)) return res;
// this style has disappeared through deletion. Add it onto our typeinstate:
if (!bAny)
{
mHTMLEditor->mTypeInState->SetProp(mCachedStyles[j].tag, mCachedStyles[j].attr, mCachedStyles[j].value);
}
}
}
return NS_OK;
}
nsresult
nsHTMLEditRules::ClearCachedStyles()
{
// clear the mPresent bits in mCachedStyles array
PRInt32 j;
for (j=0; j<SIZE_STYLE_TABLE; j++)
{
mCachedStyles[j].mPresent = PR_FALSE;
mCachedStyles[j].value.Truncate(0);
}
return NS_OK;
}
nsresult
nsHTMLEditRules::AdjustSpecialBreaks(PRBool aSafeToAskFrames)
{

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

@ -47,12 +47,26 @@
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsEditorUtils.h"
#include "TypeInState.h"
class nsVoidArray;
class nsIDOMElement;
class nsIEditor;
class nsHTMLEditor;
struct StyleCache : public PropItem
{
PRBool mPresent;
StyleCache() : PropItem(nsnull, nsString(), nsString()), mPresent(PR_FALSE){};
StyleCache(nsIAtom *aTag, const nsAString &aAttr, const nsAString &aValue) :
PropItem(aTag, aAttr, aValue), mPresent(PR_FALSE) {};
~StyleCache() {};
};
#define SIZE_STYLE_TABLE 19
class nsHTMLEditRules : public nsIHTMLEditRules, public nsTextEditRules, public nsIEditActionListener
{
public:
@ -113,8 +127,6 @@ protected:
kBlockEnd
};
// nsHTMLEditRules implementation methods
nsresult WillInsert(nsISelection *aSelection, PRBool *aCancel);
#ifdef XXX_DEAD_CODE
@ -239,6 +251,9 @@ protected:
nsresult GetTopEnclosingMailCite(nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutCiteNode, PRBool aPlaintext);
nsresult PopListItem(nsIDOMNode *aListItem, PRBool *aOutOfList);
nsresult RemoveListStructure(nsIDOMNode *aList);
nsresult CacheInlineStyles(nsIDOMNode *aNode);
nsresult ReapplyCachedStyles();
nsresult ClearCachedStyles();
nsresult AdjustSpecialBreaks(PRBool aSafeToAskFrames = PR_FALSE);
nsresult AdjustWhitespace(nsISelection *aSelection);
nsresult PinSelectionToNewBlock(nsISelection *aSelection);
@ -268,11 +283,13 @@ protected:
nsCOMPtr<nsIDOMRange> mDocChangeRange;
PRPackedBool mListenerEnabled;
PRPackedBool mReturnInEmptyLIKillsList;
PRPackedBool mDidDeleteSelection;
PRPackedBool mDidRangedDelete;
nsCOMPtr<nsIDOMRange> mUtilRange;
PRUint32 mJoinOffset; // need to remember an int across willJoin/didJoin...
nsCOMPtr<nsIDOMNode> mNewBlock;
nsRangeStore mRangeItem;
StyleCache mCachedStyles[SIZE_STYLE_TABLE];
};
nsresult NS_NewHTMLEditRules(nsIEditRules** aInstancePtrResult);

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

@ -217,6 +217,9 @@ nsHTMLEditor::~nsHTMLEditor()
if (mHTMLCSSUtils)
delete mHTMLCSSUtils;
// free any default style propItems
RemoveAllDefaultProperties();
}
NS_IMPL_ADDREF_INHERITED(nsHTMLEditor, nsEditor)
@ -4573,7 +4576,7 @@ void nsHTMLEditor::IsTextPropertySetByContent(nsIDOMNode *aNode,
const nsAString *aValue,
PRBool &aIsSet,
nsIDOMNode **aStyleNode,
nsAString *outValue) const
nsAString *outValue)
{
nsresult result;
aIsSet = PR_FALSE; // must be initialized to false for code below to work

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

@ -110,7 +110,8 @@ public:
kOpSetTextProperty = 3010,
kOpRemoveTextProperty = 3011,
kOpHTMLPaste = 3012,
kOpLoadHTML = 3013
kOpLoadHTML = 3013,
kOpResetTextProperties = 3014
};
enum ResizingRequestID
@ -150,6 +151,16 @@ public:
NS_IMETHOD ParseStyleAttrIntoCSSRule(const nsAString& aString,
nsIDOMCSSStyleRule **_retval);
NS_IMETHOD AddDefaultProperty(nsIAtom *aProperty,
const nsAString & aAttribute,
const nsAString & aValue);
NS_IMETHOD RemoveDefaultProperty(nsIAtom *aProperty,
const nsAString & aAttribute,
const nsAString & aValue);
NS_IMETHOD RemoveAllDefaultProperties();
NS_IMETHOD SetCSSInlineProperty(nsIAtom *aProperty,
const nsAString & aAttribute,
const nsAString & aValue);
@ -646,7 +657,7 @@ protected:
const nsAString *aValue,
PRBool &aIsSet,
nsIDOMNode **aStyleNode,
nsAString *outValue = nsnull) const;
nsAString *outValue = nsnull);
void ResetTextSelectionForRange(nsIDOMNode *aParent,
PRInt32 aStartOffset,
@ -781,6 +792,7 @@ protected:
const nsAString *aAttribute,
nsCOMPtr<nsIDOMNode> *outLeftNode = nsnull,
nsCOMPtr<nsIDOMNode> *outRightNode = nsnull);
nsresult ApplyDefaultProperties();
nsresult RemoveStyleInside(nsIDOMNode *aNode,
nsIAtom *aProperty,
const nsAString *aAttribute,
@ -824,7 +836,8 @@ protected:
PRBool *aFirst,
PRBool *aAny,
PRBool *aAll,
nsAString *outValue);
nsAString *outValue,
PRBool aCheckDefaults = PR_TRUE);
nsresult HasStyleOrIdOrClass(nsIDOMElement * aElement, PRBool *aHasStyleOrIdOrClass);
nsresult RemoveElementIfNoStyleOrIdOrClass(nsIDOMElement * aElement, nsIAtom * aTag);
@ -866,6 +879,9 @@ protected:
nsStringArray mStyleSheetURLs;
nsCOMArray<nsICSSStyleSheet> mStyleSheets;
PRInt32 mNumStyleSheets;
// an array for holding default style settings
nsVoidArray mDefaultStyles;
// Maintain a static parser service ...
static nsCOMPtr<nsIParserService> sParserService;

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

@ -66,6 +66,59 @@
static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID);
static NS_DEFINE_IID(kSubtreeIteratorCID, NS_SUBTREEITERATOR_CID);
NS_IMETHODIMP nsHTMLEditor::AddDefaultProperty(nsIAtom *aProperty,
const nsAString & aAttribute,
const nsAString & aValue)
{
nsresult res = NS_OK;
nsString outValue;
PRInt32 index;
nsString attr(aAttribute);
if (TypeInState::FindPropInList(aProperty, attr, &outValue, mDefaultStyles, index))
{
PropItem *item = (PropItem*)mDefaultStyles[index];
item->value = aValue;
}
else
{
nsString value(aValue);
PropItem *propItem = new PropItem(aProperty, attr, value);
mDefaultStyles.AppendElement((void*)propItem);
}
return res;
}
NS_IMETHODIMP nsHTMLEditor::RemoveDefaultProperty(nsIAtom *aProperty,
const nsAString & aAttribute,
const nsAString & aValue)
{
nsresult res = NS_OK;
nsString outValue;
PRInt32 index;
nsString attr(aAttribute);
if (TypeInState::FindPropInList(aProperty, attr, &outValue, mDefaultStyles, index))
{
PropItem *item = (PropItem*)mDefaultStyles[index];
if (item) delete item;
mDefaultStyles.RemoveElementAt(index);
}
return res;
}
NS_IMETHODIMP nsHTMLEditor::RemoveAllDefaultProperties()
{
PRInt32 j, defcon = mDefaultStyles.Count();
for (j=0; j<defcon; j++)
{
PropItem *item = (PropItem*)mDefaultStyles[j];
if (item) delete item;
}
mDefaultStyles.Clear();
return NS_OK;
}
// Add the CSS style corresponding to the HTML inline style defined
// by aProperty aAttribute and aValue to the selection
NS_IMETHODIMP nsHTMLEditor::SetCSSInlineProperty(nsIAtom *aProperty,
@ -591,6 +644,21 @@ PRBool nsHTMLEditor::NodeIsProperty(nsIDOMNode *aNode)
return PR_TRUE;
}
nsresult nsHTMLEditor::ApplyDefaultProperties()
{
nsresult res = NS_OK;
PRInt32 j, defcon = mDefaultStyles.Count();
for (j=0; j<defcon; j++)
{
PropItem *propItem = (PropItem*)mDefaultStyles[j];
if (!propItem)
return NS_ERROR_NULL_POINTER;
res = SetInlineProperty(propItem->tag, propItem->attr, propItem->value);
if (NS_FAILED(res)) return res;
}
return res;
}
nsresult nsHTMLEditor::RemoveStyleInside(nsIDOMNode *aNode,
nsIAtom *aProperty, // null here means remove all properties
const nsAString *aAttribute,
@ -915,7 +983,8 @@ nsHTMLEditor::GetInlinePropertyBase(nsIAtom *aProperty,
PRBool *aFirst,
PRBool *aAny,
PRBool *aAll,
nsAString *outValue)
nsAString *outValue,
PRBool aCheckDefaults)
{
if (!aProperty)
return NS_ERROR_NULL_POINTER;
@ -981,6 +1050,19 @@ nsHTMLEditor::GetInlinePropertyBase(nsIAtom *aProperty,
IsTextPropertySetByContent(collapsedNode, aProperty, aAttribute, aValue,
isSet, getter_AddRefs(resultNode), outValue);
*aFirst = *aAny = *aAll = isSet;
if (!isSet && aCheckDefaults)
{
// style not set, but if it is a default then it will appear if
// content is inserted, so we should report it as set (analogous to TypeInState).
PRInt32 index;
if (TypeInState::FindPropInList(aProperty, *aAttribute, outValue, mDefaultStyles, index))
{
*aFirst = *aAny = *aAll = PR_TRUE;
if (outValue)
outValue->Assign(((PropItem*)mDefaultStyles[index])->value);
}
}
return NS_OK;
}
}
@ -1152,7 +1234,12 @@ NS_IMETHODIMP nsHTMLEditor::GetInlinePropertyWithAttrValue(nsIAtom *aProperty,
NS_IMETHODIMP nsHTMLEditor::RemoveAllInlineProperties()
{
return RemoveInlinePropertyImpl(nsnull, nsnull);
nsAutoEditBatch batchIt(this);
nsAutoRules beginRulesSniffing(this, kOpResetTextProperties, nsIEditor::eNext);
nsresult res = RemoveInlinePropertyImpl(nsnull, nsnull);
if (NS_FAILED(res)) return res;
return ApplyDefaultProperties();
}
NS_IMETHODIMP nsHTMLEditor::RemoveInlineProperty(nsIAtom *aProperty, const nsAString &aAttribute)