зеркало из https://github.com/mozilla/gecko-dev.git
bug 140357: (html editor) deletion should preserve style state. r=brade; sr=kin
This commit is contained in:
Родитель
ba44a2b994
Коммит
f3491fa767
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче