[libeditor] Performance improvements.

This commit is contained in:
Fedor 2020-09-09 17:28:39 +03:00
parent 6d0d3e1922
commit df25a46b0c
12 changed files with 417 additions and 346 deletions

View File

@ -322,6 +322,15 @@ bool
CSSEditUtils::IsCSSEditableProperty(nsINode* aNode, CSSEditUtils::IsCSSEditableProperty(nsINode* aNode,
nsIAtom* aProperty, nsIAtom* aProperty,
const nsAString* aAttribute) const nsAString* aAttribute)
{
nsCOMPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
return IsCSSEditableProperty(aNode, aProperty, attribute);
}
bool
CSSEditUtils::IsCSSEditableProperty(nsINode* aNode,
nsIAtom* aProperty,
nsIAtom* aAttribute)
{ {
MOZ_ASSERT(aNode); MOZ_ASSERT(aNode);
@ -339,13 +348,12 @@ CSSEditUtils::IsCSSEditableProperty(nsINode* aNode,
nsGkAtoms::u == aProperty || nsGkAtoms::u == aProperty ||
nsGkAtoms::strike == aProperty || nsGkAtoms::strike == aProperty ||
(nsGkAtoms::font == aProperty && aAttribute && (nsGkAtoms::font == aProperty && aAttribute &&
(aAttribute->EqualsLiteral("color") || (aAttribute == nsGkAtoms::color || aAttribute == nsGkAtoms::face))) {
aAttribute->EqualsLiteral("face")))) {
return true; return true;
} }
// ALIGN attribute on elements supporting it // ALIGN attribute on elements supporting it
if (aAttribute && (aAttribute->EqualsLiteral("align")) && if (aAttribute == nsGkAtoms::align &&
node->IsAnyOfHTMLElements(nsGkAtoms::div, node->IsAnyOfHTMLElements(nsGkAtoms::div,
nsGkAtoms::p, nsGkAtoms::p,
nsGkAtoms::h1, nsGkAtoms::h1,
@ -368,7 +376,7 @@ CSSEditUtils::IsCSSEditableProperty(nsINode* aNode,
return true; return true;
} }
if (aAttribute && (aAttribute->EqualsLiteral("valign")) && if (aAttribute == nsGkAtoms::valign &&
node->IsAnyOfHTMLElements(nsGkAtoms::col, node->IsAnyOfHTMLElements(nsGkAtoms::col,
nsGkAtoms::colgroup, nsGkAtoms::colgroup,
nsGkAtoms::tbody, nsGkAtoms::tbody,
@ -381,59 +389,52 @@ CSSEditUtils::IsCSSEditableProperty(nsINode* aNode,
} }
// attributes TEXT, BACKGROUND and BGCOLOR on BODY // attributes TEXT, BACKGROUND and BGCOLOR on BODY
if (aAttribute && node->IsHTMLElement(nsGkAtoms::body) && if (node->IsHTMLElement(nsGkAtoms::body) &&
(aAttribute->EqualsLiteral("text") (aAttribute == nsGkAtoms::text || aAttribute == nsGkAtoms::background ||
|| aAttribute->EqualsLiteral("background") aAttribute == nsGkAtoms::bgcolor)) {
|| aAttribute->EqualsLiteral("bgcolor"))) {
return true; return true;
} }
// attribute BGCOLOR on other elements // attribute BGCOLOR on other elements
if (aAttribute && aAttribute->EqualsLiteral("bgcolor")) { if (aAttribute == nsGkAtoms::bgcolor) {
return true; return true;
} }
// attributes HEIGHT, WIDTH and NOWRAP on TD and TH // attributes HEIGHT, WIDTH and NOWRAP on TD and TH
if (aAttribute && if (node->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th) &&
node->IsAnyOfHTMLElements(nsGkAtoms::td, nsGkAtoms::th) && (aAttribute == nsGkAtoms::height || aAttribute == nsGkAtoms::width ||
(aAttribute->EqualsLiteral("height") aAttribute == nsGkAtoms::nowrap)) {
|| aAttribute->EqualsLiteral("width")
|| aAttribute->EqualsLiteral("nowrap"))) {
return true; return true;
} }
// attributes HEIGHT and WIDTH on TABLE // attributes HEIGHT and WIDTH on TABLE
if (aAttribute && node->IsHTMLElement(nsGkAtoms::table) && if (node->IsHTMLElement(nsGkAtoms::table) &&
(aAttribute->EqualsLiteral("height") (aAttribute == nsGkAtoms::height || aAttribute == nsGkAtoms::width)) {
|| aAttribute->EqualsLiteral("width"))) {
return true; return true;
} }
// attributes SIZE and WIDTH on HR // attributes SIZE and WIDTH on HR
if (aAttribute && node->IsHTMLElement(nsGkAtoms::hr) && if (node->IsHTMLElement(nsGkAtoms::hr) &&
(aAttribute->EqualsLiteral("size") (aAttribute == nsGkAtoms::size || aAttribute == nsGkAtoms::width)) {
|| aAttribute->EqualsLiteral("width"))) {
return true; return true;
} }
// attribute TYPE on OL UL LI // attribute TYPE on OL UL LI
if (aAttribute && if (node->IsAnyOfHTMLElements(nsGkAtoms::ol, nsGkAtoms::ul,
node->IsAnyOfHTMLElements(nsGkAtoms::ol, nsGkAtoms::ul,
nsGkAtoms::li) && nsGkAtoms::li) &&
aAttribute->EqualsLiteral("type")) { aAttribute == nsGkAtoms::type) {
return true; return true;
} }
if (aAttribute && node->IsHTMLElement(nsGkAtoms::img) && if (node->IsHTMLElement(nsGkAtoms::img) &&
(aAttribute->EqualsLiteral("border") (aAttribute == nsGkAtoms::border || aAttribute == nsGkAtoms::width ||
|| aAttribute->EqualsLiteral("width") aAttribute == nsGkAtoms::height)) {
|| aAttribute->EqualsLiteral("height"))) {
return true; return true;
} }
// other elements that we can align using CSS even if they // other elements that we can align using CSS even if they
// can't carry the html ALIGN attribute // can't carry the html ALIGN attribute
if (aAttribute && aAttribute->EqualsLiteral("align") && if (aAttribute == nsGkAtoms::align &&
node->IsAnyOfHTMLElements(nsGkAtoms::ul, node->IsAnyOfHTMLElements(nsGkAtoms::ul,
nsGkAtoms::ol, nsGkAtoms::ol,
nsGkAtoms::dl, nsGkAtoms::dl,
@ -818,7 +819,7 @@ void
CSSEditUtils::GenerateCSSDeclarationsFromHTMLStyle( CSSEditUtils::GenerateCSSDeclarationsFromHTMLStyle(
Element* aElement, Element* aElement,
nsIAtom* aHTMLProperty, nsIAtom* aHTMLProperty,
const nsAString* aAttribute, nsIAtom* aAttribute,
const nsAString* aValue, const nsAString* aValue,
nsTArray<nsIAtom*>& cssPropertyArray, nsTArray<nsIAtom*>& cssPropertyArray,
nsTArray<nsString>& cssValueArray, nsTArray<nsString>& cssValueArray,
@ -838,21 +839,20 @@ CSSEditUtils::GenerateCSSDeclarationsFromHTMLStyle(
} else if (nsGkAtoms::tt == aHTMLProperty) { } else if (nsGkAtoms::tt == aHTMLProperty) {
equivTable = ttEquivTable; equivTable = ttEquivTable;
} else if (aAttribute) { } else if (aAttribute) {
if (nsGkAtoms::font == aHTMLProperty && if (nsGkAtoms::font == aHTMLProperty && aAttribute == nsGkAtoms::color) {
aAttribute->EqualsLiteral("color")) {
equivTable = fontColorEquivTable; equivTable = fontColorEquivTable;
} else if (nsGkAtoms::font == aHTMLProperty && } else if (nsGkAtoms::font == aHTMLProperty &&
aAttribute->EqualsLiteral("face")) { aAttribute == nsGkAtoms::face) {
equivTable = fontFaceEquivTable; equivTable = fontFaceEquivTable;
} else if (aAttribute->EqualsLiteral("bgcolor")) { } else if (aAttribute == nsGkAtoms::bgcolor) {
equivTable = bgcolorEquivTable; equivTable = bgcolorEquivTable;
} else if (aAttribute->EqualsLiteral("background")) { } else if (aAttribute == nsGkAtoms::background) {
equivTable = backgroundImageEquivTable; equivTable = backgroundImageEquivTable;
} else if (aAttribute->EqualsLiteral("text")) { } else if (aAttribute == nsGkAtoms::text) {
equivTable = textColorEquivTable; equivTable = textColorEquivTable;
} else if (aAttribute->EqualsLiteral("border")) { } else if (aAttribute == nsGkAtoms::border) {
equivTable = borderEquivTable; equivTable = borderEquivTable;
} else if (aAttribute->EqualsLiteral("align")) { } else if (aAttribute == nsGkAtoms::align) {
if (aElement->IsHTMLElement(nsGkAtoms::table)) { if (aElement->IsHTMLElement(nsGkAtoms::table)) {
equivTable = tableAlignEquivTable; equivTable = tableAlignEquivTable;
} else if (aElement->IsHTMLElement(nsGkAtoms::hr)) { } else if (aElement->IsHTMLElement(nsGkAtoms::hr)) {
@ -863,17 +863,17 @@ CSSEditUtils::GenerateCSSDeclarationsFromHTMLStyle(
} else { } else {
equivTable = textAlignEquivTable; equivTable = textAlignEquivTable;
} }
} else if (aAttribute->EqualsLiteral("valign")) { } else if (aAttribute == nsGkAtoms::valign) {
equivTable = verticalAlignEquivTable; equivTable = verticalAlignEquivTable;
} else if (aAttribute->EqualsLiteral("nowrap")) { } else if (aAttribute == nsGkAtoms::nowrap) {
equivTable = nowrapEquivTable; equivTable = nowrapEquivTable;
} else if (aAttribute->EqualsLiteral("width")) { } else if (aAttribute == nsGkAtoms::width) {
equivTable = widthEquivTable; equivTable = widthEquivTable;
} else if (aAttribute->EqualsLiteral("height") || } else if (aAttribute == nsGkAtoms::height ||
(aElement->IsHTMLElement(nsGkAtoms::hr) && (aElement->IsHTMLElement(nsGkAtoms::hr) &&
aAttribute->EqualsLiteral("size"))) { aAttribute == nsGkAtoms::size)) {
equivTable = heightEquivTable; equivTable = heightEquivTable;
} else if (aAttribute->EqualsLiteral("type") && } else if (aAttribute == nsGkAtoms::type &&
aElement->IsAnyOfHTMLElements(nsGkAtoms::ol, aElement->IsAnyOfHTMLElements(nsGkAtoms::ol,
nsGkAtoms::ul, nsGkAtoms::ul,
nsGkAtoms::li)) { nsGkAtoms::li)) {
@ -890,40 +890,46 @@ CSSEditUtils::GenerateCSSDeclarationsFromHTMLStyle(
// aValue for the node, and return in aCount the number of CSS properties set // aValue for the node, and return in aCount the number of CSS properties set
// by the call. The Element version returns aCount instead. // by the call. The Element version returns aCount instead.
int32_t int32_t
CSSEditUtils::SetCSSEquivalentToHTMLStyle(Element* aElement, CSSEditUtils::SetCSSEquivalentToHTMLStyle(nsIDOMNode* aNode,
nsIAtom* aProperty, nsIAtom* aProperty,
const nsAString* aAttribute, const nsAString* aAttribute,
const nsAString* aValue, const nsAString* aValue,
bool aSuppressTransaction) bool aSuppressTransaction)
{ {
MOZ_ASSERT(aElement && aProperty);
MOZ_ASSERT_IF(aAttribute, aValue); MOZ_ASSERT_IF(aAttribute, aValue);
int32_t count;
// This can only fail if SetCSSProperty fails, which should only happen if // This can only fail if SetCSSProperty fails, which should only happen if
// something is pretty badly wrong. In this case we assert so that hopefully // something is pretty badly wrong. In this case we assert so that hopefully
// someone will notice, but there's nothing more sensible to do than just // someone will notice, but there's nothing more sensible to do than just
// return the count and carry on. // return the count and carry on.
nsresult rv = SetCSSEquivalentToHTMLStyle(aElement->AsDOMNode(), nsCOMPtr<Element> element = do_QueryInterface(aNode);
aProperty, aAttribute, return SetCSSEquivalentToHTMLStyle(element,
aValue, &count, aProperty, aAttribute,
aSuppressTransaction); aValue, aSuppressTransaction);
NS_ASSERTION(NS_SUCCEEDED(rv), "SetCSSEquivalentToHTMLStyle failed");
NS_ENSURE_SUCCESS(rv, count);
return count;
} }
nsresult int32_t
CSSEditUtils::SetCSSEquivalentToHTMLStyle(nsIDOMNode* aNode, CSSEditUtils::SetCSSEquivalentToHTMLStyle(Element* aElement,
nsIAtom* aHTMLProperty, nsIAtom* aHTMLProperty,
const nsAString* aAttribute, const nsAString* aAttribute,
const nsAString* aValue, const nsAString* aValue,
int32_t* aCount,
bool aSuppressTransaction) bool aSuppressTransaction)
{ {
nsCOMPtr<Element> element = do_QueryInterface(aNode); nsCOMPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
*aCount = 0; return SetCSSEquivalentToHTMLStyle(aElement, aHTMLProperty, attribute,
if (!element || !IsCSSEditableProperty(element, aHTMLProperty, aAttribute)) { aValue, aSuppressTransaction);
return NS_OK; }
int32_t
CSSEditUtils::SetCSSEquivalentToHTMLStyle(Element* aElement,
nsIAtom* aHTMLProperty,
nsIAtom* aAttribute,
const nsAString* aValue,
bool aSuppressTransaction)
{
MOZ_ASSERT(aElement);
if (!IsCSSEditableProperty(aElement, aHTMLProperty, aAttribute)) {
return 0;
} }
// we can apply the styles only if the node is an element and if we have // we can apply the styles only if the node is an element and if we have
@ -932,18 +938,20 @@ CSSEditUtils::SetCSSEquivalentToHTMLStyle(nsIDOMNode* aNode,
// Find the CSS equivalence to the HTML style // Find the CSS equivalence to the HTML style
nsTArray<nsIAtom*> cssPropertyArray; nsTArray<nsIAtom*> cssPropertyArray;
nsTArray<nsString> cssValueArray; nsTArray<nsString> cssValueArray;
GenerateCSSDeclarationsFromHTMLStyle(element, aHTMLProperty, aAttribute, GenerateCSSDeclarationsFromHTMLStyle(aElement, aHTMLProperty, aAttribute,
aValue, cssPropertyArray, cssValueArray, aValue, cssPropertyArray, cssValueArray,
false); false);
// set the individual CSS inline styles // set the individual CSS inline styles
*aCount = cssPropertyArray.Length(); size_t count = cssPropertyArray.Length();
for (int32_t index = 0; index < *aCount; index++) { for (size_t index = 0; index < count; index++) {
nsresult rv = SetCSSProperty(*element, *cssPropertyArray[index], nsresult rv = SetCSSProperty(*aElement, *cssPropertyArray[index],
cssValueArray[index], aSuppressTransaction); cssValueArray[index], aSuppressTransaction);
NS_ENSURE_SUCCESS(rv, rv); if (NS_WARN_IF(NS_FAILED(rv))) {
return 0;
}
} }
return NS_OK; return count;
} }
// Remove from aNode the CSS inline style equivalent to HTMLProperty/aAttribute/aValue for the node // Remove from aNode the CSS inline style equivalent to HTMLProperty/aAttribute/aValue for the node
@ -955,20 +963,22 @@ CSSEditUtils::RemoveCSSEquivalentToHTMLStyle(nsIDOMNode* aNode,
bool aSuppressTransaction) bool aSuppressTransaction)
{ {
nsCOMPtr<Element> element = do_QueryInterface(aNode); nsCOMPtr<Element> element = do_QueryInterface(aNode);
NS_ENSURE_TRUE(element, NS_OK); nsCOMPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
return RemoveCSSEquivalentToHTMLStyle(element, aHTMLProperty, aAttribute, return RemoveCSSEquivalentToHTMLStyle(element, aHTMLProperty, attribute,
aValue, aSuppressTransaction); aValue, aSuppressTransaction);
} }
nsresult nsresult
CSSEditUtils::RemoveCSSEquivalentToHTMLStyle(Element* aElement, CSSEditUtils::RemoveCSSEquivalentToHTMLStyle(Element* aElement,
nsIAtom* aHTMLProperty, nsIAtom* aHTMLProperty,
const nsAString* aAttribute, nsIAtom* aAttribute,
const nsAString* aValue, const nsAString* aValue,
bool aSuppressTransaction) bool aSuppressTransaction)
{ {
MOZ_ASSERT(aElement); if (NS_WARN_IF(!aElement)) {
return NS_OK;
}
if (!IsCSSEditableProperty(aElement, aHTMLProperty, aAttribute)) { if (!IsCSSEditableProperty(aElement, aHTMLProperty, aAttribute)) {
return NS_OK; return NS_OK;
@ -1003,7 +1013,7 @@ CSSEditUtils::RemoveCSSEquivalentToHTMLStyle(Element* aElement,
nsresult nsresult
CSSEditUtils::GetCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode, CSSEditUtils::GetCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode,
nsIAtom* aHTMLProperty, nsIAtom* aHTMLProperty,
const nsAString* aAttribute, nsIAtom* aAttribute,
nsAString& aValueString, nsAString& aValueString,
StyleType aStyleType) StyleType aStyleType)
{ {
@ -1020,7 +1030,8 @@ CSSEditUtils::GetCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode,
nsTArray<nsString> cssValueArray; nsTArray<nsString> cssValueArray;
// get the CSS equivalence with last param true indicating we want only the // get the CSS equivalence with last param true indicating we want only the
// "gettable" properties // "gettable" properties
GenerateCSSDeclarationsFromHTMLStyle(theElement, aHTMLProperty, aAttribute, nullptr, GenerateCSSDeclarationsFromHTMLStyle(theElement, aHTMLProperty, aAttribute,
nullptr,
cssPropertyArray, cssValueArray, true); cssPropertyArray, cssValueArray, true);
int32_t count = cssPropertyArray.Length(); int32_t count = cssPropertyArray.Length();
for (int32_t index = 0; index < count; index++) { for (int32_t index = 0; index < count; index++) {
@ -1066,48 +1077,58 @@ CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode,
StyleType aStyleType) StyleType aStyleType)
{ {
MOZ_ASSERT(aNode && aProperty); MOZ_ASSERT(aNode && aProperty);
bool isSet; nsCOMPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
nsresult rv = IsCSSEquivalentToHTMLInlineStyleSet(aNode->AsDOMNode(), return IsCSSEquivalentToHTMLInlineStyleSet(aNode,
aProperty, aAttribute, aProperty, attribute,
isSet, aValue, aStyleType); aValue, aStyleType);
NS_ENSURE_SUCCESS(rv, false);
return isSet;
} }
nsresult bool
CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode* aNode,
nsIAtom* aProperty,
const nsAString* aAttribute,
nsAString& aValue,
StyleType aStyleType)
{
MOZ_ASSERT(aNode && aProperty);
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
nsCOMPtr<nsIAtom> attribute = aAttribute ? NS_Atomize(*aAttribute) : nullptr;
return IsCSSEquivalentToHTMLInlineStyleSet(node, aProperty, attribute,
aValue, aStyleType);
}
bool
CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet( CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(
nsIDOMNode* aNode, nsINode* aNode,
nsIAtom* aHTMLProperty, nsIAtom* aHTMLProperty,
const nsAString* aHTMLAttribute, nsIAtom* aHTMLAttribute,
bool& aIsSet,
nsAString& valueString, nsAString& valueString,
StyleType aStyleType) StyleType aStyleType)
{ {
NS_ENSURE_TRUE(aNode, NS_ERROR_NULL_POINTER); NS_ENSURE_TRUE(aNode, false);
nsAutoString htmlValueString(valueString); nsAutoString htmlValueString(valueString);
aIsSet = false; bool isSet = false;
nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
do { do {
valueString.Assign(htmlValueString); valueString.Assign(htmlValueString);
// get the value of the CSS equivalent styles // get the value of the CSS equivalent styles
nsresult rv = nsresult rv =
GetCSSEquivalentToHTMLInlineStyleSet(node, aHTMLProperty, aHTMLAttribute, GetCSSEquivalentToHTMLInlineStyleSet(aNode, aHTMLProperty, aHTMLAttribute,
valueString, aStyleType); valueString, aStyleType);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, false);
// early way out if we can // early way out if we can
if (valueString.IsEmpty()) { if (valueString.IsEmpty()) {
return NS_OK; return isSet;
} }
if (nsGkAtoms::b == aHTMLProperty) { if (nsGkAtoms::b == aHTMLProperty) {
if (valueString.EqualsLiteral("bold")) { if (valueString.EqualsLiteral("bold")) {
aIsSet = true; isSet = true;
} else if (valueString.EqualsLiteral("normal")) { } else if (valueString.EqualsLiteral("normal")) {
aIsSet = false; isSet = false;
} else if (valueString.EqualsLiteral("bolder")) { } else if (valueString.EqualsLiteral("bolder")) {
aIsSet = true; isSet = true;
valueString.AssignLiteral("bold"); valueString.AssignLiteral("bold");
} else { } else {
int32_t weight = 0; int32_t weight = 0;
@ -1115,32 +1136,31 @@ CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(
nsAutoString value(valueString); nsAutoString value(valueString);
weight = value.ToInteger(&errorCode); weight = value.ToInteger(&errorCode);
if (400 < weight) { if (400 < weight) {
aIsSet = true; isSet = true;
valueString.AssignLiteral("bold"); valueString.AssignLiteral("bold");
} else { } else {
aIsSet = false; isSet = false;
valueString.AssignLiteral("normal"); valueString.AssignLiteral("normal");
} }
} }
} else if (nsGkAtoms::i == aHTMLProperty) { } else if (nsGkAtoms::i == aHTMLProperty) {
if (valueString.EqualsLiteral("italic") || if (valueString.EqualsLiteral("italic") ||
valueString.EqualsLiteral("oblique")) { valueString.EqualsLiteral("oblique")) {
aIsSet = true; isSet = true;
} }
} else if (nsGkAtoms::u == aHTMLProperty) { } else if (nsGkAtoms::u == aHTMLProperty) {
nsAutoString val; nsAutoString val;
val.AssignLiteral("underline"); val.AssignLiteral("underline");
aIsSet = ChangeStyleTransaction::ValueIncludes(valueString, val); isSet = ChangeStyleTransaction::ValueIncludes(valueString, val);
} else if (nsGkAtoms::strike == aHTMLProperty) { } else if (nsGkAtoms::strike == aHTMLProperty) {
nsAutoString val; nsAutoString val;
val.AssignLiteral("line-through"); val.AssignLiteral("line-through");
aIsSet = ChangeStyleTransaction::ValueIncludes(valueString, val); isSet = ChangeStyleTransaction::ValueIncludes(valueString, val);
} else if (aHTMLAttribute && } else if ((nsGkAtoms::font == aHTMLProperty &&
((nsGkAtoms::font == aHTMLProperty && aHTMLAttribute == nsGkAtoms::color) ||
aHTMLAttribute->EqualsLiteral("color")) || aHTMLAttribute == nsGkAtoms::bgcolor) {
aHTMLAttribute->EqualsLiteral("bgcolor"))) {
if (htmlValueString.IsEmpty()) { if (htmlValueString.IsEmpty()) {
aIsSet = true; isSet = true;
} else { } else {
nscolor rgba; nscolor rgba;
nsAutoString subStr; nsAutoString subStr;
@ -1174,54 +1194,53 @@ CSSEditUtils::IsCSSEquivalentToHTMLInlineStyleSet(
htmlColor.Append(char16_t(')')); htmlColor.Append(char16_t(')'));
} }
aIsSet = htmlColor.Equals(valueString, isSet = htmlColor.Equals(valueString,
nsCaseInsensitiveStringComparator()); nsCaseInsensitiveStringComparator());
} else { } else {
aIsSet = htmlValueString.Equals(valueString, isSet = htmlValueString.Equals(valueString,
nsCaseInsensitiveStringComparator()); nsCaseInsensitiveStringComparator());
} }
} }
} else if (nsGkAtoms::tt == aHTMLProperty) { } else if (nsGkAtoms::tt == aHTMLProperty) {
aIsSet = StringBeginsWith(valueString, NS_LITERAL_STRING("monospace")); isSet = StringBeginsWith(valueString, NS_LITERAL_STRING("monospace"));
} else if (nsGkAtoms::font == aHTMLProperty && aHTMLAttribute && } else if (nsGkAtoms::font == aHTMLProperty && aHTMLAttribute &&
aHTMLAttribute->EqualsLiteral("face")) { aHTMLAttribute == nsGkAtoms::face) {
if (!htmlValueString.IsEmpty()) { if (!htmlValueString.IsEmpty()) {
const char16_t commaSpace[] = { char16_t(','), char16_t(' '), 0 }; const char16_t commaSpace[] = { char16_t(','), char16_t(' '), 0 };
const char16_t comma[] = { char16_t(','), 0 }; const char16_t comma[] = { char16_t(','), 0 };
htmlValueString.ReplaceSubstring(commaSpace, comma); htmlValueString.ReplaceSubstring(commaSpace, comma);
nsAutoString valueStringNorm(valueString); nsAutoString valueStringNorm(valueString);
valueStringNorm.ReplaceSubstring(commaSpace, comma); valueStringNorm.ReplaceSubstring(commaSpace, comma);
aIsSet = htmlValueString.Equals(valueStringNorm, isSet = htmlValueString.Equals(valueStringNorm,
nsCaseInsensitiveStringComparator()); nsCaseInsensitiveStringComparator());
} else { } else {
aIsSet = true; isSet = true;
} }
return NS_OK; return isSet;
} else if (aHTMLAttribute && aHTMLAttribute->EqualsLiteral("align")) { } else if (aHTMLAttribute == nsGkAtoms::align) {
aIsSet = true; isSet = true;
} else { } else {
aIsSet = false; return false;
return NS_OK;
} }
if (!htmlValueString.IsEmpty() && if (!htmlValueString.IsEmpty() &&
htmlValueString.Equals(valueString, htmlValueString.Equals(valueString,
nsCaseInsensitiveStringComparator())) { nsCaseInsensitiveStringComparator())) {
aIsSet = true; isSet = true;
} }
if (htmlValueString.EqualsLiteral("-moz-editor-invert-value")) { if (htmlValueString.EqualsLiteral("-moz-editor-invert-value")) {
aIsSet = !aIsSet; isSet = !isSet;
} }
if (nsGkAtoms::u == aHTMLProperty || nsGkAtoms::strike == aHTMLProperty) { if (nsGkAtoms::u == aHTMLProperty || nsGkAtoms::strike == aHTMLProperty) {
// unfortunately, the value of the text-decoration property is not inherited. // unfortunately, the value of the text-decoration property is not inherited.
// that means that we have to look at ancestors of node to see if they are underlined // that means that we have to look at ancestors of node to see if they are underlined
node = node->GetParentElement(); // set to null if it's not a dom element aNode = aNode->GetParentElement(); // set to null if it's not a dom element
} }
} while ((nsGkAtoms::u == aHTMLProperty || } while ((nsGkAtoms::u == aHTMLProperty ||
nsGkAtoms::strike == aHTMLProperty) && !aIsSet && node); nsGkAtoms::strike == aHTMLProperty) && !isSet && aNode);
return NS_OK; return isSet;
} }
void void

View File

@ -90,6 +90,8 @@ public:
*/ */
bool IsCSSEditableProperty(nsINode* aNode, nsIAtom* aProperty, bool IsCSSEditableProperty(nsINode* aNode, nsIAtom* aProperty,
const nsAString* aAttribute); const nsAString* aAttribute);
bool IsCSSEditableProperty(nsINode* aNode, nsIAtom* aProperty,
nsIAtom* aAttribute);
/** /**
* Adds/remove a CSS declaration to the STYLE atrribute carried by a given * Adds/remove a CSS declaration to the STYLE atrribute carried by a given
@ -188,14 +190,14 @@ public:
* *
* @param aNode [IN] A DOM node. * @param aNode [IN] A DOM node.
* @param aHTMLProperty [IN] An atom containing an HTML property. * @param aHTMLProperty [IN] An atom containing an HTML property.
* @param aAttribute [IN] A pointer to an attribute name or nullptr if * @param aAttribute [IN] An atom of attribute name or nullptr if
* irrelevant. * irrelevant.
* @param aValueString [OUT] The list of CSS values. * @param aValueString [OUT] The list of CSS values.
* @param aStyleType [IN] eSpecified or eComputed. * @param aStyleType [IN] eSpecified or eComputed.
*/ */
nsresult GetCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode, nsresult GetCSSEquivalentToHTMLInlineStyleSet(nsINode* aNode,
nsIAtom* aHTMLProperty, nsIAtom* aHTMLProperty,
const nsAString* aAttribute, nsIAtom* aAttribute,
nsAString& aValueString, nsAString& aValueString,
StyleType aStyleType); StyleType aStyleType);
@ -205,16 +207,20 @@ public:
* *
* @param aNode [IN] A DOM node. * @param aNode [IN] A DOM node.
* @param aHTMLProperty [IN] An atom containing an HTML property. * @param aHTMLProperty [IN] An atom containing an HTML property.
* @param aAttribute [IN] A pointer to an attribute name or nullptr if * @param aAttribute [IN] A pointer/atom to an attribute name or nullptr
* irrelevant. * if irrelevant.
* @param aIsSet [OUT] A boolean being true if the css properties are
* set.
* @param aValueString [IN/OUT] The attribute value (in) the list of CSS * @param aValueString [IN/OUT] The attribute value (in) the list of CSS
* values (out). * values (out).
* @param aStyleType [IN] eSpecified or eComputed. * @param aStyleType [IN] eSpecified or eComputed.
* * @return A boolean being true if the css properties are
* The nsIContent variant returns aIsSet instead of using an out parameter. * set.
*/ */
bool IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aContent,
nsIAtom* aProperty,
nsIAtom* aAttribute,
nsAString& aValue,
StyleType aStyleType);
bool IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aContent, bool IsCSSEquivalentToHTMLInlineStyleSet(nsINode* aContent,
nsIAtom* aProperty, nsIAtom* aProperty,
const nsAString* aAttribute, const nsAString* aAttribute,
@ -227,12 +233,11 @@ public:
nsAString& aValue, nsAString& aValue,
StyleType aStyleType); StyleType aStyleType);
nsresult IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode* aNode, bool IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode* aNode,
nsIAtom* aHTMLProperty, nsIAtom* aProperty,
const nsAString* aAttribute, const nsAString* aAttribute,
bool& aIsSet, nsAString& aValue,
nsAString& aValueString, StyleType aStyleType);
StyleType aStyleType);
/** /**
* Adds to the node the CSS inline styles equivalent to the HTML style * Adds to the node the CSS inline styles equivalent to the HTML style
@ -240,27 +245,29 @@ public:
* *
* @param aNode [IN] A DOM node. * @param aNode [IN] A DOM node.
* @param aHTMLProperty [IN] An atom containing an HTML property. * @param aHTMLProperty [IN] An atom containing an HTML property.
* @param aAttribute [IN] A pointer to an attribute name or nullptr if * @param aAttribute [IN] A pointer/atom to an attribute name or nullptr
* irrelevant. * if irrelevant.
* @param aValue [IN] The attribute value. * @param aValue [IN] The attribute value.
* @param aCount [OUT] The number of CSS properties set by the call.
* @param aSuppressTransaction [IN] A boolean indicating, when true, * @param aSuppressTransaction [IN] A boolean indicating, when true,
* that no transaction should be recorded. * that no transaction should be recorded.
* *
* aCount is returned by the dom::Element variant instead of being an out * @return The number of CSS properties set by the call.
* parameter.
*/ */
int32_t SetCSSEquivalentToHTMLStyle(dom::Element* aElement,
nsIAtom* aProperty,
nsIAtom* aAttribute,
const nsAString* aValue,
bool aSuppressTransaction);
int32_t SetCSSEquivalentToHTMLStyle(dom::Element* aElement, int32_t SetCSSEquivalentToHTMLStyle(dom::Element* aElement,
nsIAtom* aProperty, nsIAtom* aProperty,
const nsAString* aAttribute, const nsAString* aAttribute,
const nsAString* aValue, const nsAString* aValue,
bool aSuppressTransaction); bool aSuppressTransaction);
nsresult SetCSSEquivalentToHTMLStyle(nsIDOMNode* aNode, int32_t SetCSSEquivalentToHTMLStyle(nsIDOMNode* aNode,
nsIAtom* aHTMLProperty, nsIAtom* aHTMLProperty,
const nsAString* aAttribute, const nsAString* aAttribute,
const nsAString* aValue, const nsAString* aValue,
int32_t* aCount, bool aSuppressTransaction);
bool aSuppressTransaction);
/** /**
* Removes from the node the CSS inline styles equivalent to the HTML style. * Removes from the node the CSS inline styles equivalent to the HTML style.
@ -284,7 +291,7 @@ public:
* *
* @param aElement [IN] A DOM Element (must not be null). * @param aElement [IN] A DOM Element (must not be null).
* @param aHTMLProperty [IN] An atom containing an HTML property. * @param aHTMLProperty [IN] An atom containing an HTML property.
* @param aAttribute [IN] A pointer to an attribute name or nullptr if * @param aAttribute [IN] An atom to an attribute name or nullptr if
* irrelevant. * irrelevant.
* @param aValue [IN] The attribute value. * @param aValue [IN] The attribute value.
* @param aSuppressTransaction [IN] A boolean indicating, when true, * @param aSuppressTransaction [IN] A boolean indicating, when true,
@ -292,7 +299,7 @@ public:
*/ */
nsresult RemoveCSSEquivalentToHTMLStyle(dom::Element* aElement, nsresult RemoveCSSEquivalentToHTMLStyle(dom::Element* aElement,
nsIAtom* aHTMLProperty, nsIAtom* aHTMLProperty,
const nsAString* aAttribute, nsIAtom* aAttribute,
const nsAString* aValue, const nsAString* aValue,
bool aSuppressTransaction); bool aSuppressTransaction);
@ -409,7 +416,7 @@ private:
* *
* @param aNode [IN] The DOM node. * @param aNode [IN] The DOM node.
* @param aHTMLProperty [IN] An atom containing an HTML property. * @param aHTMLProperty [IN] An atom containing an HTML property.
* @param aAttribute [IN] A pointer to an attribute name or nullptr * @param aAttribute [IN] An atom to an attribute name or nullptr
* if irrelevant * if irrelevant
* @param aValue [IN] The attribute value. * @param aValue [IN] The attribute value.
* @param aPropertyArray [OUT] The array of CSS properties. * @param aPropertyArray [OUT] The array of CSS properties.
@ -422,7 +429,7 @@ private:
*/ */
void GenerateCSSDeclarationsFromHTMLStyle(dom::Element* aNode, void GenerateCSSDeclarationsFromHTMLStyle(dom::Element* aNode,
nsIAtom* aHTMLProperty, nsIAtom* aHTMLProperty,
const nsAString* aAttribute, nsIAtom* aAttribute,
const nsAString* aValue, const nsAString* aValue,
nsTArray<nsIAtom*>& aPropertyArray, nsTArray<nsIAtom*>& aPropertyArray,
nsTArray<nsString>& aValueArray, nsTArray<nsString>& aValueArray,

View File

@ -1235,12 +1235,23 @@ EditorBase::SetAttribute(nsIDOMElement* aElement,
const nsAString& aAttribute, const nsAString& aAttribute,
const nsAString& aValue) const nsAString& aValue)
{ {
if (NS_WARN_IF(aAttribute.IsEmpty())) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<Element> element = do_QueryInterface(aElement); nsCOMPtr<Element> element = do_QueryInterface(aElement);
NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER); NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute); nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
return SetAttribute(element, attribute, aValue);
}
nsresult
EditorBase::SetAttribute(Element* aElement,
nsIAtom* aAttribute,
const nsAString& aValue)
{
RefPtr<ChangeAttributeTransaction> transaction = RefPtr<ChangeAttributeTransaction> transaction =
CreateTxnForSetAttribute(*element, *attribute, aValue); CreateTxnForSetAttribute(*aElement, *aAttribute, aValue);
return DoTransaction(transaction); return DoTransaction(transaction);
} }
@ -1269,12 +1280,22 @@ NS_IMETHODIMP
EditorBase::RemoveAttribute(nsIDOMElement* aElement, EditorBase::RemoveAttribute(nsIDOMElement* aElement,
const nsAString& aAttribute) const nsAString& aAttribute)
{ {
if (NS_WARN_IF(aAttribute.IsEmpty())) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<Element> element = do_QueryInterface(aElement); nsCOMPtr<Element> element = do_QueryInterface(aElement);
NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER); NS_ENSURE_TRUE(element, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute); nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
return RemoveAttribute(element, attribute);
}
nsresult
EditorBase::RemoveAttribute(Element* aElement,
nsIAtom* aAttribute)
{
RefPtr<ChangeAttributeTransaction> transaction = RefPtr<ChangeAttributeTransaction> transaction =
CreateTxnForRemoveAttribute(*element, *attribute); CreateTxnForRemoveAttribute(*aElement, *aAttribute);
return DoTransaction(transaction); return DoTransaction(transaction);
} }
@ -2249,25 +2270,28 @@ EditorBase::CloneAttribute(const nsAString& aAttribute,
nsIDOMNode* aSourceNode) nsIDOMNode* aSourceNode)
{ {
NS_ENSURE_TRUE(aDestNode && aSourceNode, NS_ERROR_NULL_POINTER); NS_ENSURE_TRUE(aDestNode && aSourceNode, NS_ERROR_NULL_POINTER);
if (NS_WARN_IF(aAttribute.IsEmpty())) {
nsCOMPtr<nsIDOMElement> destElement = do_QueryInterface(aDestNode); return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMElement> sourceElement = do_QueryInterface(aSourceNode);
NS_ENSURE_TRUE(destElement && sourceElement, NS_ERROR_NO_INTERFACE);
nsAutoString attrValue;
bool isAttrSet;
nsresult rv = GetAttributeValue(sourceElement,
aAttribute,
attrValue,
&isAttrSet);
NS_ENSURE_SUCCESS(rv, rv);
if (isAttrSet) {
rv = SetAttribute(destElement, aAttribute, attrValue);
} else {
rv = RemoveAttribute(destElement, aAttribute);
} }
return rv; nsCOMPtr<Element> destElement = do_QueryInterface(aDestNode);
nsCOMPtr<Element> sourceElement = do_QueryInterface(aSourceNode);
NS_ENSURE_TRUE(destElement && sourceElement, NS_ERROR_NO_INTERFACE);
nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
return CloneAttribute(attribute, destElement, sourceElement);
}
nsresult
EditorBase::CloneAttribute(nsIAtom* aAttribute,
Element* aDestElement,
Element* aSourceElement)
{
nsAutoString attrValue;
if (aSourceElement->GetAttr(kNameSpaceID_None, aAttribute, attrValue)) {
return SetAttribute(aDestElement, aAttribute, attrValue);
}
return RemoveAttribute(aDestElement, aAttribute);
} }
/** /**
@ -2306,11 +2330,9 @@ EditorBase::CloneAttributes(Element* aDest,
RefPtr<nsDOMAttributeMap> destAttributes = aDest->Attributes(); RefPtr<nsDOMAttributeMap> destAttributes = aDest->Attributes();
while (RefPtr<Attr> attr = destAttributes->Item(0)) { while (RefPtr<Attr> attr = destAttributes->Item(0)) {
if (destInBody) { if (destInBody) {
RemoveAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(aDest)), RemoveAttribute(aDest, attr->NodeInfo()->NameAtom());
attr->NodeName());
} else { } else {
ErrorResult ignored; aDest->UnsetAttr(kNameSpaceID_None, attr->NodeInfo()->NameAtom(), true);
aDest->RemoveAttribute(attr->NodeName(), ignored);
} }
} }
@ -2322,13 +2344,13 @@ EditorBase::CloneAttributes(Element* aDest,
nsAutoString value; nsAutoString value;
attr->GetValue(value); attr->GetValue(value);
if (destInBody) { if (destInBody) {
SetAttributeOrEquivalent(static_cast<nsIDOMElement*>(GetAsDOMNode(aDest)), SetAttributeOrEquivalent(aDest, attr->NodeInfo()->NameAtom(), value,
attr->NodeName(), value, false); false);
} else { } else {
// The element is not inserted in the document yet, we don't want to put // The element is not inserted in the document yet, we don't want to put
// a transaction on the UndoStack // a transaction on the UndoStack
SetAttributeOrEquivalent(static_cast<nsIDOMElement*>(GetAsDOMNode(aDest)), SetAttributeOrEquivalent(aDest, attr->NodeInfo()->NameAtom(), value,
attr->NodeName(), value, true); true);
} }
} }
} }
@ -4678,21 +4700,32 @@ EditorBase::CreateHTMLContent(nsIAtom* aTag)
kNameSpaceID_XHTML); kNameSpaceID_XHTML);
} }
nsresult NS_IMETHODIMP
EditorBase::SetAttributeOrEquivalent(nsIDOMElement* aElement, EditorBase::SetAttributeOrEquivalent(nsIDOMElement* aElement,
const nsAString& aAttribute, const nsAString& aAttribute,
const nsAString& aValue, const nsAString& aValue,
bool aSuppressTransaction) bool aSuppressTransaction)
{ {
return SetAttribute(aElement, aAttribute, aValue); nsCOMPtr<Element> element = do_QueryInterface(aElement);
if (NS_WARN_IF(!element)) {
return NS_ERROR_NULL_POINTER;
}
nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
return SetAttributeOrEquivalent(element, attribute, aValue,
aSuppressTransaction);
} }
nsresult NS_IMETHODIMP
EditorBase::RemoveAttributeOrEquivalent(nsIDOMElement* aElement, EditorBase::RemoveAttributeOrEquivalent(nsIDOMElement* aElement,
const nsAString& aAttribute, const nsAString& aAttribute,
bool aSuppressTransaction) bool aSuppressTransaction)
{ {
return RemoveAttribute(aElement, aAttribute); nsCOMPtr<Element> element = do_QueryInterface(aElement);
if (NS_WARN_IF(!element)) {
return NS_ERROR_NULL_POINTER;
}
nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
return RemoveAttributeOrEquivalent(element, attribute, aSuppressTransaction);
} }
nsresult nsresult

View File

@ -291,6 +291,19 @@ public:
nsresult JoinNodes(nsINode& aLeftNode, nsINode& aRightNode); nsresult JoinNodes(nsINode& aLeftNode, nsINode& aRightNode);
nsresult MoveNode(nsIContent* aNode, nsINode* aParent, int32_t aOffset); nsresult MoveNode(nsIContent* aNode, nsINode* aParent, int32_t aOffset);
nsresult CloneAttribute(nsIAtom* aAttribute, Element* aDestElement,
Element* aSourceElement);
nsresult RemoveAttribute(Element* aElement, nsIAtom* aAttribute);
virtual nsresult RemoveAttributeOrEquivalent(Element* aElement,
nsIAtom* aAttribute,
bool aSuppressTransaction) = 0;
nsresult SetAttribute(Element* aElement, nsIAtom* aAttribute,
const nsAString& aValue);
virtual nsresult SetAttributeOrEquivalent(Element* aElement,
nsIAtom* aAttribute,
const nsAString& aValue,
bool aSuppressTransaction) = 0;
/** /**
* Method to replace certain CreateElementNS() calls. * Method to replace certain CreateElementNS() calls.
* *

View File

@ -840,19 +840,18 @@ HTMLEditRules::GetAlignment(bool* aMixed,
NS_ENSURE_TRUE(nodeToExamine, NS_ERROR_NULL_POINTER); NS_ENSURE_TRUE(nodeToExamine, NS_ERROR_NULL_POINTER);
NS_NAMED_LITERAL_STRING(typeAttrName, "align");
nsCOMPtr<Element> blockParent = htmlEditor->GetBlock(*nodeToExamine); nsCOMPtr<Element> blockParent = htmlEditor->GetBlock(*nodeToExamine);
NS_ENSURE_TRUE(blockParent, NS_ERROR_FAILURE); NS_ENSURE_TRUE(blockParent, NS_ERROR_FAILURE);
if (htmlEditor->IsCSSEnabled() && if (htmlEditor->IsCSSEnabled() &&
htmlEditor->mCSSEditUtils->IsCSSEditableProperty(blockParent, nullptr, htmlEditor->mCSSEditUtils->IsCSSEditableProperty(blockParent, nullptr,
&typeAttrName)) { nsGkAtoms::align)) {
// We are in CSS mode and we know how to align this element with CSS // We are in CSS mode and we know how to align this element with CSS
nsAutoString value; nsAutoString value;
// Let's get the value(s) of text-align or margin-left/margin-right // Let's get the value(s) of text-align or margin-left/margin-right
htmlEditor->mCSSEditUtils->GetCSSEquivalentToHTMLInlineStyleSet( htmlEditor->mCSSEditUtils->GetCSSEquivalentToHTMLInlineStyleSet(
blockParent, nullptr, &typeAttrName, value, CSSEditUtils::eComputed); blockParent, nullptr, nsGkAtoms::align, value, CSSEditUtils::eComputed);
if (value.EqualsLiteral("center") || if (value.EqualsLiteral("center") ||
value.EqualsLiteral("-moz-center") || value.EqualsLiteral("-moz-center") ||
value.EqualsLiteral("auto auto")) { value.EqualsLiteral("auto auto")) {
@ -1510,10 +1509,11 @@ HTMLEditRules::WillInsertBreak(Selection& aSelection,
nsCOMPtr<Element> blockParent = htmlEditor->GetBlock(node); nsCOMPtr<Element> blockParent = htmlEditor->GetBlock(node);
NS_ENSURE_TRUE(blockParent, NS_ERROR_FAILURE); NS_ENSURE_TRUE(blockParent, NS_ERROR_FAILURE);
// If the active editing host is an inline element, or if the active editing // When there is an active editing host (the <body> if it's in designMode)
// host is the block parent itself, just append a br. // and a block which becomes the parent of line breaker is in it, do the
// standard thing.
nsCOMPtr<Element> host = htmlEditor->GetActiveEditingHost(); nsCOMPtr<Element> host = htmlEditor->GetActiveEditingHost();
if (!EditorUtils::IsDescendantOf(blockParent, host)) { if (host && !EditorUtils::IsDescendantOf(blockParent, host)) {
nsresult rv = StandardBreakImpl(node, offset, aSelection); nsresult rv = StandardBreakImpl(node, offset, aSelection);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
*aHandled = true; *aHandled = true;
@ -3303,15 +3303,15 @@ HTMLEditRules::WillMakeList(Selection* aSelection,
} }
} }
NS_ENSURE_STATE(mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor);
nsCOMPtr<nsIDOMElement> curElement = do_QueryInterface(curNode); nsCOMPtr<Element> curElement = do_QueryInterface(curNode);
NS_NAMED_LITERAL_STRING(typestr, "type");
if (aBulletType && !aBulletType->IsEmpty()) { if (aBulletType && !aBulletType->IsEmpty()) {
rv = mHTMLEditor->SetAttribute(curElement, typestr, *aBulletType); rv = mHTMLEditor->SetAttribute(curElement, nsGkAtoms::type,
*aBulletType);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
} }
} else { } else {
rv = mHTMLEditor->RemoveAttribute(curElement, typestr); rv = mHTMLEditor->RemoveAttribute(curElement, nsGkAtoms::type);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
} }
@ -4756,7 +4756,7 @@ HTMLEditRules::WillAlign(Selection& aSelection,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (useCSS) { if (useCSS) {
htmlEditor->mCSSEditUtils->SetCSSEquivalentToHTMLStyle( htmlEditor->mCSSEditUtils->SetCSSEquivalentToHTMLStyle(
curNode->AsElement(), nullptr, &NS_LITERAL_STRING("align"), curNode->AsElement(), nullptr, nsGkAtoms::align,
&aAlignType, false); &aAlignType, false);
curDiv = nullptr; curDiv = nullptr;
continue; continue;
@ -4837,7 +4837,6 @@ HTMLEditRules::AlignBlockContents(nsIDOMNode* aNode,
nsCOMPtr<nsINode> node = do_QueryInterface(aNode); nsCOMPtr<nsINode> node = do_QueryInterface(aNode);
NS_ENSURE_TRUE(node && alignType, NS_ERROR_NULL_POINTER); NS_ENSURE_TRUE(node && alignType, NS_ERROR_NULL_POINTER);
nsCOMPtr<nsIContent> firstChild, lastChild; nsCOMPtr<nsIContent> firstChild, lastChild;
nsCOMPtr<Element> divNode;
bool useCSS = mHTMLEditor->IsCSSEnabled(); bool useCSS = mHTMLEditor->IsCSSEnabled();
@ -4845,24 +4844,25 @@ HTMLEditRules::AlignBlockContents(nsIDOMNode* aNode,
firstChild = mHTMLEditor->GetFirstEditableChild(*node); firstChild = mHTMLEditor->GetFirstEditableChild(*node);
NS_ENSURE_STATE(mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor);
lastChild = mHTMLEditor->GetLastEditableChild(*node); lastChild = mHTMLEditor->GetLastEditableChild(*node);
NS_NAMED_LITERAL_STRING(attr, "align");
if (!firstChild) { if (!firstChild) {
// this cell has no content, nothing to align // this cell has no content, nothing to align
} else if (firstChild == lastChild && } else if (firstChild == lastChild &&
firstChild->IsHTMLElement(nsGkAtoms::div)) { firstChild->IsHTMLElement(nsGkAtoms::div)) {
// the cell already has a div containing all of its content: just // the cell already has a div containing all of its content: just
// act on this div. // act on this div.
nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(firstChild); RefPtr<Element> divElem = firstChild->AsElement();
if (useCSS) { if (useCSS) {
NS_ENSURE_STATE(mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor);
nsresult rv = mHTMLEditor->SetAttributeOrEquivalent(divElem, attr, nsresult rv = mHTMLEditor->SetAttributeOrEquivalent(divElem,
nsGkAtoms::align,
*alignType, false); *alignType, false);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
} }
} else { } else {
NS_ENSURE_STATE(mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor);
nsresult rv = mHTMLEditor->SetAttribute(divElem, attr, *alignType); nsresult rv = mHTMLEditor->SetAttribute(divElem, nsGkAtoms::align,
*alignType);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
} }
@ -4870,28 +4870,29 @@ HTMLEditRules::AlignBlockContents(nsIDOMNode* aNode,
} else { } else {
// else we need to put in a div, set the alignment, and toss in all the children // else we need to put in a div, set the alignment, and toss in all the children
NS_ENSURE_STATE(mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor);
divNode = mHTMLEditor->CreateNode(nsGkAtoms::div, node, 0); RefPtr<Element> divElem = mHTMLEditor->CreateNode(nsGkAtoms::div, node, 0);
NS_ENSURE_STATE(divNode); NS_ENSURE_STATE(divElem);
// set up the alignment on the div // set up the alignment on the div
nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(divNode);
if (useCSS) { if (useCSS) {
NS_ENSURE_STATE(mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor);
nsresult rv = nsresult rv =
mHTMLEditor->SetAttributeOrEquivalent(divElem, attr, *alignType, false); mHTMLEditor->SetAttributeOrEquivalent(divElem, nsGkAtoms::align,
*alignType, false);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
} }
} else { } else {
NS_ENSURE_STATE(mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor);
nsresult rv = mHTMLEditor->SetAttribute(divElem, attr, *alignType); nsresult rv =
mHTMLEditor->SetAttribute(divElem, nsGkAtoms::align, *alignType);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
} }
} }
// tuck the children into the end of the active div // tuck the children into the end of the active div
while (lastChild && (lastChild != divNode)) { while (lastChild && (lastChild != divElem)) {
NS_ENSURE_STATE(mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor);
nsresult rv = mHTMLEditor->MoveNode(lastChild, divNode, 0); nsresult rv = mHTMLEditor->MoveNode(lastChild, divElem, 0);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_STATE(mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor);
lastChild = mHTMLEditor->GetLastEditableChild(*node); lastChild = mHTMLEditor->GetLastEditableChild(*node);
@ -6498,10 +6499,14 @@ HTMLEditRules::SplitParagraph(nsIDOMNode *aPara,
// split the paragraph // split the paragraph
NS_ENSURE_STATE(mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor);
NS_ENSURE_STATE(selNode->IsContent()); NS_ENSURE_STATE(selNode->IsContent());
mHTMLEditor->SplitNodeDeep(*para, *selNode->AsContent(), *aOffset, int32_t offset =
HTMLEditor::EmptyContainers::yes, mHTMLEditor->SplitNodeDeep(*para, *selNode->AsContent(), *aOffset,
getter_AddRefs(leftPara), HTMLEditor::EmptyContainers::yes,
getter_AddRefs(rightPara)); getter_AddRefs(leftPara),
getter_AddRefs(rightPara));
if (NS_WARN_IF(offset == -1)) {
return NS_ERROR_FAILURE;
}
// get rid of the break, if it is visible (otherwise it may be needed to prevent an empty p) // get rid of the break, if it is visible (otherwise it may be needed to prevent an empty p)
NS_ENSURE_STATE(mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor);
if (mHTMLEditor->IsVisBreak(aBRNode)) { if (mHTMLEditor->IsVisBreak(aBRNode)) {
@ -6511,9 +6516,9 @@ HTMLEditRules::SplitParagraph(nsIDOMNode *aPara,
} }
// remove ID attribute on the paragraph we just created // remove ID attribute on the paragraph we just created
nsCOMPtr<nsIDOMElement> rightElt = do_QueryInterface(rightPara); RefPtr<Element> rightElt = rightPara->AsElement();
NS_ENSURE_STATE(mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor);
rv = mHTMLEditor->RemoveAttribute(rightElt, NS_LITERAL_STRING("id")); rv = mHTMLEditor->RemoveAttribute(rightElt, nsGkAtoms::id);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// check both halves of para to see if we need mozBR // check both halves of para to see if we need mozBR
@ -7143,9 +7148,9 @@ HTMLEditRules::CacheInlineStyles(nsIDOMNode* aNode)
isSet, &outValue); isSet, &outValue);
} else { } else {
NS_ENSURE_STATE(mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor);
mHTMLEditor->mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(aNode, isSet = mHTMLEditor->mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(
mCachedStyles[j].tag, &(mCachedStyles[j].attr), isSet, outValue, aNode, mCachedStyles[j].tag, &(mCachedStyles[j].attr), outValue,
CSSEditUtils::eComputed); CSSEditUtils::eComputed);
} }
if (isSet) { if (isSet) {
mCachedStyles[j].mPresent = true; mCachedStyles[j].mPresent = true;
@ -8388,18 +8393,18 @@ HTMLEditRules::RemoveAlignment(nsIDOMNode* aNode,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} else if (isBlock || HTMLEditUtils::IsHR(child)) { } else if (isBlock || HTMLEditUtils::IsHR(child)) {
// the current node is a block element // the current node is a block element
nsCOMPtr<nsIDOMElement> curElem = do_QueryInterface(child); nsCOMPtr<Element> curElem = do_QueryInterface(child);
if (HTMLEditUtils::SupportsAlignAttr(child)) { if (HTMLEditUtils::SupportsAlignAttr(child)) {
// remove the ALIGN attribute if this element can have it // remove the ALIGN attribute if this element can have it
NS_ENSURE_STATE(mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor);
rv = mHTMLEditor->RemoveAttribute(curElem, NS_LITERAL_STRING("align")); rv = mHTMLEditor->RemoveAttribute(curElem, nsGkAtoms::align);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
if (useCSS) { if (useCSS) {
if (HTMLEditUtils::IsTable(child) || HTMLEditUtils::IsHR(child)) { if (HTMLEditUtils::IsTable(child) || HTMLEditUtils::IsHR(child)) {
NS_ENSURE_STATE(mHTMLEditor); NS_ENSURE_STATE(mHTMLEditor);
rv = mHTMLEditor->SetAttributeOrEquivalent(curElem, rv = mHTMLEditor->SetAttributeOrEquivalent(curElem,
NS_LITERAL_STRING("align"), nsGkAtoms::align,
aAlignType, false); aAlignType, false);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
@ -8519,21 +8524,17 @@ HTMLEditRules::AlignBlock(Element& aElement,
nsresult rv = RemoveAlignment(aElement.AsDOMNode(), aAlignType, nsresult rv = RemoveAlignment(aElement.AsDOMNode(), aAlignType,
aContentsOnly == ContentsOnly::yes); aContentsOnly == ContentsOnly::yes);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
NS_NAMED_LITERAL_STRING(attr, "align");
if (htmlEditor->IsCSSEnabled()) { if (htmlEditor->IsCSSEnabled()) {
// Let's use CSS alignment; we use margin-left and margin-right for tables // Let's use CSS alignment; we use margin-left and margin-right for tables
// and text-align for other block-level elements // and text-align for other block-level elements
rv = htmlEditor->SetAttributeOrEquivalent( rv = htmlEditor->SetAttributeOrEquivalent(
static_cast<nsIDOMElement*>(aElement.AsDOMNode()), &aElement, nsGkAtoms::align, aAlignType, false);
attr, aAlignType, false);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} else { } else {
// HTML case; this code is supposed to be called ONLY if the element // HTML case; this code is supposed to be called ONLY if the element
// supports the align attribute but we'll never know... // supports the align attribute but we'll never know...
if (HTMLEditUtils::SupportsAlignAttr(aElement.AsDOMNode())) { if (HTMLEditUtils::SupportsAlignAttr(aElement.AsDOMNode())) {
rv = htmlEditor->SetAttribute( rv = htmlEditor->SetAttribute(&aElement, nsGkAtoms::align, aAlignType);
static_cast<nsIDOMElement*>(aElement.AsDOMNode()),
attr, aAlignType);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
} }

View File

@ -2529,7 +2529,7 @@ HTMLEditor::CreateElementWithDefaults(const nsAString& aTagName)
// New call to use instead to get proper HTML element, bug 39919 // New call to use instead to get proper HTML element, bug 39919
nsCOMPtr<nsIAtom> realTagAtom = NS_Atomize(realTagName); nsCOMPtr<nsIAtom> realTagAtom = NS_Atomize(realTagName);
nsCOMPtr<Element> newElement = CreateHTMLContent(realTagAtom); RefPtr<Element> newElement = CreateHTMLContent(realTagAtom);
if (!newElement) { if (!newElement) {
return nullptr; return nullptr;
} }
@ -2561,8 +2561,7 @@ HTMLEditor::CreateElementWithDefaults(const nsAString& aTagName)
} else if (tagName.EqualsLiteral("td")) { } else if (tagName.EqualsLiteral("td")) {
nsresult rv = nsresult rv =
SetAttributeOrEquivalent( SetAttributeOrEquivalent(
static_cast<nsIDOMElement*>(newElement->AsDOMNode()), newElement, nsGkAtoms::valign, NS_LITERAL_STRING("top"), true);
NS_LITERAL_STRING("valign"), NS_LITERAL_STRING("top"), true);
NS_ENSURE_SUCCESS(rv, nullptr); NS_ENSURE_SUCCESS(rv, nullptr);
} }
// ADD OTHER TAGS HERE // ADD OTHER TAGS HERE
@ -4390,87 +4389,83 @@ HTMLEditor::IsEmptyNodeImpl(nsINode* aNode,
// add to aElement the CSS inline styles corresponding to the HTML attribute // add to aElement the CSS inline styles corresponding to the HTML attribute
// aAttribute with its value aValue // aAttribute with its value aValue
nsresult nsresult
HTMLEditor::SetAttributeOrEquivalent(nsIDOMElement* aElement, HTMLEditor::SetAttributeOrEquivalent(Element* aElement,
const nsAString& aAttribute, nsIAtom* aAttribute,
const nsAString& aValue, const nsAString& aValue,
bool aSuppressTransaction) bool aSuppressTransaction)
{ {
MOZ_ASSERT(aElement);
MOZ_ASSERT(aAttribute);
nsAutoScriptBlocker scriptBlocker; nsAutoScriptBlocker scriptBlocker;
if (IsCSSEnabled() && mCSSEditUtils) { if (!IsCSSEnabled() || !mCSSEditUtils) {
int32_t count; // we are not in an HTML+CSS editor; let's set the attribute the HTML way
nsresult rv = return aSuppressTransaction ?
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(aElement, nullptr, aElement->SetAttr(kNameSpaceID_None, aAttribute, aValue, true) :
&aAttribute, &aValue, SetAttribute(aElement, aAttribute, aValue);
&count,
aSuppressTransaction);
NS_ENSURE_SUCCESS(rv, rv);
if (count) {
// we found an equivalence ; let's remove the HTML attribute itself if it is set
nsAutoString existingValue;
bool wasSet = false;
rv = GetAttributeValue(aElement, aAttribute, existingValue, &wasSet);
NS_ENSURE_SUCCESS(rv, rv);
if (!wasSet) {
return NS_OK;
}
return aSuppressTransaction ? aElement->RemoveAttribute(aAttribute) :
RemoveAttribute(aElement, aAttribute);
}
// count is an integer that represents the number of CSS declarations applied to the
// element. If it is zero, we found no equivalence in this implementation for the
// attribute
if (aAttribute.EqualsLiteral("style")) {
// if it is the style attribute, just add the new value to the existing style
// attribute's value
nsAutoString existingValue;
bool wasSet = false;
nsresult rv = GetAttributeValue(aElement, NS_LITERAL_STRING("style"),
existingValue, &wasSet);
NS_ENSURE_SUCCESS(rv, rv);
existingValue.Append(' ');
existingValue.Append(aValue);
return aSuppressTransaction ?
aElement->SetAttribute(aAttribute, existingValue) :
SetAttribute(aElement, aAttribute, existingValue);
}
// we have no CSS equivalence for this attribute and it is not the style
// attribute; let's set it the good'n'old HTML way
return aSuppressTransaction ? aElement->SetAttribute(aAttribute, aValue) :
SetAttribute(aElement, aAttribute, aValue);
} }
// we are not in an HTML+CSS editor; let's set the attribute the HTML way int32_t count =
return aSuppressTransaction ? aElement->SetAttribute(aAttribute, aValue) : mCSSEditUtils->SetCSSEquivalentToHTMLStyle(aElement, nullptr,
SetAttribute(aElement, aAttribute, aValue); aAttribute, &aValue,
aSuppressTransaction);
if (count) {
// we found an equivalence ; let's remove the HTML attribute itself if it
// is set
nsAutoString existingValue;
if (!aElement->GetAttr(kNameSpaceID_None, aAttribute, existingValue)) {
return NS_OK;
}
return aSuppressTransaction ?
aElement->UnsetAttr(kNameSpaceID_None, aAttribute, true) :
RemoveAttribute(aElement, aAttribute);
}
// count is an integer that represents the number of CSS declarations applied
// to the element. If it is zero, we found no equivalence in this
// implementation for the attribute
if (aAttribute == nsGkAtoms::style) {
// if it is the style attribute, just add the new value to the existing
// style attribute's value
nsAutoString existingValue;
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::style, existingValue);
existingValue.Append(' ');
existingValue.Append(aValue);
return aSuppressTransaction ?
aElement->SetAttr(kNameSpaceID_None, aAttribute, existingValue, true) :
SetAttribute(aElement, aAttribute, existingValue);
}
// we have no CSS equivalence for this attribute and it is not the style
// attribute; let's set it the good'n'old HTML way
return aSuppressTransaction ?
aElement->SetAttr(kNameSpaceID_None, aAttribute, aValue, true) :
SetAttribute(aElement, aAttribute, aValue);
} }
nsresult nsresult
HTMLEditor::RemoveAttributeOrEquivalent(nsIDOMElement* aElement, HTMLEditor::RemoveAttributeOrEquivalent(Element* aElement,
const nsAString& aAttribute, nsIAtom* aAttribute,
bool aSuppressTransaction) bool aSuppressTransaction)
{ {
nsCOMPtr<dom::Element> element = do_QueryInterface(aElement); MOZ_ASSERT(aElement);
NS_ENSURE_TRUE(element, NS_OK); MOZ_ASSERT(aAttribute);
nsCOMPtr<nsIAtom> attribute = NS_Atomize(aAttribute);
MOZ_ASSERT(attribute);
if (IsCSSEnabled() && mCSSEditUtils) { if (IsCSSEnabled() && mCSSEditUtils) {
nsresult rv = nsresult rv =
mCSSEditUtils->RemoveCSSEquivalentToHTMLStyle( mCSSEditUtils->RemoveCSSEquivalentToHTMLStyle(
element, nullptr, &aAttribute, nullptr, aSuppressTransaction); aElement, nullptr, aAttribute, nullptr, aSuppressTransaction);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
if (!element->HasAttr(kNameSpaceID_None, attribute)) { if (!aElement->HasAttr(kNameSpaceID_None, aAttribute)) {
return NS_OK; return NS_OK;
} }
return aSuppressTransaction ? return aSuppressTransaction ?
element->UnsetAttr(kNameSpaceID_None, attribute, /* aNotify = */ true) : aElement->UnsetAttr(kNameSpaceID_None, aAttribute, /* aNotify = */ true) :
RemoveAttribute(aElement, aAttribute); RemoveAttribute(aElement, aAttribute);
} }
@ -4523,7 +4518,6 @@ HTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (!cancel && !handled) { if (!cancel && !handled) {
// Loop through the ranges in the selection // Loop through the ranges in the selection
NS_NAMED_LITERAL_STRING(bgcolor, "bgcolor");
for (uint32_t i = 0; i < selection->RangeCount(); i++) { for (uint32_t i = 0; i < selection->RangeCount(); i++) {
RefPtr<nsRange> range = selection->GetRangeAt(i); RefPtr<nsRange> range = selection->GetRangeAt(i);
NS_ENSURE_TRUE(range, NS_ERROR_FAILURE); NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
@ -4542,13 +4536,15 @@ HTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
if (blockParent && cachedBlockParent != blockParent) { if (blockParent && cachedBlockParent != blockParent) {
cachedBlockParent = blockParent; cachedBlockParent = blockParent;
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr, mCSSEditUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
&bgcolor, &aColor, false); nsGkAtoms::bgcolor,
&aColor, false);
} }
} else if (startNode == endNode && } else if (startNode == endNode &&
startNode->IsHTMLElement(nsGkAtoms::body) && isCollapsed) { startNode->IsHTMLElement(nsGkAtoms::body) && isCollapsed) {
// No block in the document, let's apply the background to the body // No block in the document, let's apply the background to the body
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(startNode->AsElement(), mCSSEditUtils->SetCSSEquivalentToHTMLStyle(startNode->AsElement(),
nullptr, &bgcolor, &aColor, nullptr, nsGkAtoms::bgcolor,
&aColor,
false); false);
} else if (startNode == endNode && (endOffset - startOffset == 1 || } else if (startNode == endNode && (endOffset - startOffset == 1 ||
(!startOffset && !endOffset))) { (!startOffset && !endOffset))) {
@ -4559,7 +4555,8 @@ HTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
if (blockParent && cachedBlockParent != blockParent) { if (blockParent && cachedBlockParent != blockParent) {
cachedBlockParent = blockParent; cachedBlockParent = blockParent;
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr, mCSSEditUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
&bgcolor, &aColor, false); nsGkAtoms::bgcolor,
&aColor, false);
} }
} else { } else {
// Not the easy case. Range not contained in single text node. There // Not the easy case. Range not contained in single text node. There
@ -4602,7 +4599,8 @@ HTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
if (blockParent && cachedBlockParent != blockParent) { if (blockParent && cachedBlockParent != blockParent) {
cachedBlockParent = blockParent; cachedBlockParent = blockParent;
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr, mCSSEditUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
&bgcolor, &aColor, nsGkAtoms::bgcolor,
&aColor,
false); false);
} }
} }
@ -4613,7 +4611,8 @@ HTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
if (blockParent && cachedBlockParent != blockParent) { if (blockParent && cachedBlockParent != blockParent) {
cachedBlockParent = blockParent; cachedBlockParent = blockParent;
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr, mCSSEditUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
&bgcolor, &aColor, nsGkAtoms::bgcolor,
&aColor,
false); false);
} }
} }
@ -4627,7 +4626,8 @@ HTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
if (blockParent && cachedBlockParent != blockParent) { if (blockParent && cachedBlockParent != blockParent) {
cachedBlockParent = blockParent; cachedBlockParent = blockParent;
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr, mCSSEditUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
&bgcolor, &aColor, nsGkAtoms::bgcolor,
&aColor,
false); false);
} }
} }

View File

@ -118,6 +118,16 @@ public:
virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override; virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
virtual bool IsEditable(nsINode* aNode) override; virtual bool IsEditable(nsINode* aNode) override;
using EditorBase::IsEditable; using EditorBase::IsEditable;
virtual nsresult RemoveAttributeOrEquivalent(
Element* aElement,
nsIAtom* aAttribute,
bool aSuppressTransaction) override;
virtual nsresult SetAttributeOrEquivalent(Element* aElement,
nsIAtom* aAttribute,
const nsAString& aValue,
bool aSuppressTransaction) override;
using EditorBase::RemoveAttributeOrEquivalent;
using EditorBase::SetAttributeOrEquivalent;
// nsStubMutationObserver overrides // nsStubMutationObserver overrides
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
@ -329,14 +339,6 @@ public:
*/ */
virtual nsresult SelectEntireDocument(Selection* aSelection) override; virtual nsresult SelectEntireDocument(Selection* aSelection) override;
NS_IMETHOD SetAttributeOrEquivalent(nsIDOMElement* aElement,
const nsAString& aAttribute,
const nsAString& aValue,
bool aSuppressTransaction) override;
NS_IMETHOD RemoveAttributeOrEquivalent(nsIDOMElement* aElement,
const nsAString& aAttribute,
bool aSuppressTransaction) override;
/** /**
* Join together any adjacent editable text nodes in the range. * Join together any adjacent editable text nodes in the range.
*/ */

View File

@ -926,35 +926,30 @@ HTMLEditor::SetFinalSize(int32_t aX,
// we want one transaction only from a user's point of view // we want one transaction only from a user's point of view
AutoEditBatch batchIt(this); AutoEditBatch batchIt(this);
NS_NAMED_LITERAL_STRING(widthStr, "width");
NS_NAMED_LITERAL_STRING(heightStr, "height");
nsCOMPtr<Element> resizedObject = do_QueryInterface(mResizedObject);
NS_ENSURE_TRUE(resizedObject, );
if (mResizedObjectIsAbsolutelyPositioned) { if (mResizedObjectIsAbsolutelyPositioned) {
if (setHeight) { if (setHeight) {
mCSSEditUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::top, y); mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::top, y);
} }
if (setWidth) { if (setWidth) {
mCSSEditUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::left, x); mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::left, x);
} }
} }
if (IsCSSEnabled() || mResizedObjectIsAbsolutelyPositioned) { if (IsCSSEnabled() || mResizedObjectIsAbsolutelyPositioned) {
if (setWidth && mResizedObject->HasAttr(kNameSpaceID_None, nsGkAtoms::width)) { if (setWidth && mResizedObject->HasAttr(kNameSpaceID_None, nsGkAtoms::width)) {
RemoveAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), widthStr); RemoveAttribute(mResizedObject, nsGkAtoms::width);
} }
if (setHeight && mResizedObject->HasAttr(kNameSpaceID_None, if (setHeight && mResizedObject->HasAttr(kNameSpaceID_None,
nsGkAtoms::height)) { nsGkAtoms::height)) {
RemoveAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), heightStr); RemoveAttribute(mResizedObject, nsGkAtoms::height);
} }
if (setWidth) { if (setWidth) {
mCSSEditUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::width, mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::width,
width); width);
} }
if (setHeight) { if (setHeight) {
mCSSEditUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::height, mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::height,
height); height);
} }
} else { } else {
@ -964,30 +959,30 @@ HTMLEditor::SetFinalSize(int32_t aX,
// triggering an immediate reflow; otherwise, we have problems // triggering an immediate reflow; otherwise, we have problems
// with asynchronous reflow // with asynchronous reflow
if (setWidth) { if (setWidth) {
mCSSEditUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::width, mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::width,
width); width);
} }
if (setHeight) { if (setHeight) {
mCSSEditUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::height, mCSSEditUtils->SetCSSPropertyPixels(*mResizedObject, *nsGkAtoms::height,
height); height);
} }
if (setWidth) { if (setWidth) {
nsAutoString w; nsAutoString w;
w.AppendInt(width); w.AppendInt(width);
SetAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), widthStr, w); SetAttribute(mResizedObject, nsGkAtoms::width, w);
} }
if (setHeight) { if (setHeight) {
nsAutoString h; nsAutoString h;
h.AppendInt(height); h.AppendInt(height);
SetAttribute(static_cast<nsIDOMElement*>(GetAsDOMNode(mResizedObject)), heightStr, h); SetAttribute(mResizedObject, nsGkAtoms::height, h);
} }
if (setWidth) { if (setWidth) {
mCSSEditUtils->RemoveCSSProperty(*resizedObject, *nsGkAtoms::width, mCSSEditUtils->RemoveCSSProperty(*mResizedObject, *nsGkAtoms::width,
EmptyString()); EmptyString());
} }
if (setHeight) { if (setHeight) {
mCSSEditUtils->RemoveCSSProperty(*resizedObject, *nsGkAtoms::height, mCSSEditUtils->RemoveCSSProperty(*mResizedObject, *nsGkAtoms::height,
EmptyString()); EmptyString());
} }
} }

View File

@ -429,7 +429,7 @@ HTMLEditor::SetInlinePropertyOnNodeImpl(nsIContent& aNode,
mCSSEditUtils->IsCSSEditableProperty(&aNode, &aProperty, mCSSEditUtils->IsCSSEditableProperty(&aNode, &aProperty,
aAttribute)) || aAttribute)) ||
// bgcolor is always done using CSS // bgcolor is always done using CSS
aAttribute->EqualsLiteral("bgcolor"); attrAtom == nsGkAtoms::bgcolor;
if (useCSS) { if (useCSS) {
nsCOMPtr<dom::Element> tmp; nsCOMPtr<dom::Element> tmp;
@ -444,12 +444,9 @@ HTMLEditor::SetInlinePropertyOnNodeImpl(nsIContent& aNode,
} }
// Add the CSS styles corresponding to the HTML style request // Add the CSS styles corresponding to the HTML style request
int32_t count; mCSSEditUtils->SetCSSEquivalentToHTMLStyle(tmp,
nsresult rv = &aProperty, attrAtom,
mCSSEditUtils->SetCSSEquivalentToHTMLStyle(tmp->AsDOMNode(), &aValue, false);
&aProperty, aAttribute,
&aValue, &count, false);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK; return NS_OK;
} }
@ -576,8 +573,9 @@ HTMLEditor::SplitStyleAbovePoint(nsCOMPtr<nsINode>* aNode,
// in this implementation for the node; let's check if it carries those // in this implementation for the node; let's check if it carries those
// CSS styles // CSS styles
nsAutoString firstValue; nsAutoString firstValue;
mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(GetAsDOMNode(node), isSet = mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(
aProperty, aAttribute, isSet, firstValue, CSSEditUtils::eSpecified); node, aProperty, aAttribute, firstValue,
CSSEditUtils::eSpecified);
} }
if (// node is the correct inline prop if (// node is the correct inline prop
(aProperty && node->IsHTMLElement(aProperty)) || (aProperty && node->IsHTMLElement(aProperty)) ||
@ -746,8 +744,6 @@ HTMLEditor::RemoveStyleInside(nsIContent& aNode,
// if we weren't passed an attribute, then we want to // if we weren't passed an attribute, then we want to
// remove any matching inlinestyles entirely // remove any matching inlinestyles entirely
if (!aAttribute || aAttribute->IsEmpty()) { if (!aAttribute || aAttribute->IsEmpty()) {
NS_NAMED_LITERAL_STRING(styleAttr, "style");
NS_NAMED_LITERAL_STRING(classAttr, "class");
bool hasStyleAttr = aNode.HasAttr(kNameSpaceID_None, nsGkAtoms::style); bool hasStyleAttr = aNode.HasAttr(kNameSpaceID_None, nsGkAtoms::style);
bool hasClassAttr = aNode.HasAttr(kNameSpaceID_None, nsGkAtoms::_class); bool hasClassAttr = aNode.HasAttr(kNameSpaceID_None, nsGkAtoms::_class);
@ -756,14 +752,14 @@ HTMLEditor::RemoveStyleInside(nsIContent& aNode,
// just remove the element... We need to create above the element // just remove the element... We need to create above the element
// a span that will carry those styles or class, then we can delete // a span that will carry those styles or class, then we can delete
// the node. // the node.
nsCOMPtr<Element> spanNode = RefPtr<Element> spanNode =
InsertContainerAbove(&aNode, nsGkAtoms::span); InsertContainerAbove(&aNode, nsGkAtoms::span);
NS_ENSURE_STATE(spanNode); NS_ENSURE_STATE(spanNode);
nsresult rv = nsresult rv =
CloneAttribute(styleAttr, spanNode->AsDOMNode(), aNode.AsDOMNode()); CloneAttribute(nsGkAtoms::style, spanNode, aNode.AsElement());
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = rv =
CloneAttribute(classAttr, spanNode->AsDOMNode(), aNode.AsDOMNode()); CloneAttribute(nsGkAtoms::_class, spanNode, aNode.AsElement());
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }
nsresult rv = RemoveContainer(&aNode); nsresult rv = RemoveContainer(&aNode);
@ -796,15 +792,17 @@ HTMLEditor::RemoveStyleInside(nsIContent& aNode,
// the HTML style defined by aProperty/aAttribute has a CSS equivalence in // the HTML style defined by aProperty/aAttribute has a CSS equivalence in
// this implementation for the node aNode; let's check if it carries those // this implementation for the node aNode; let's check if it carries those
// css styles // css styles
nsCOMPtr<nsIAtom> attribute =
aAttribute ? NS_Atomize(*aAttribute) : nullptr;
nsAutoString propertyValue; nsAutoString propertyValue;
bool isSet = mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(&aNode, bool isSet = mCSSEditUtils->IsCSSEquivalentToHTMLInlineStyleSet(&aNode,
aProperty, aAttribute, propertyValue, CSSEditUtils::eSpecified); aProperty, attribute, propertyValue, CSSEditUtils::eSpecified);
if (isSet && aNode.IsElement()) { if (isSet && aNode.IsElement()) {
// yes, tmp has the corresponding css declarations in its style attribute // yes, tmp has the corresponding css declarations in its style attribute
// let's remove them // let's remove them
mCSSEditUtils->RemoveCSSEquivalentToHTMLStyle(aNode.AsElement(), mCSSEditUtils->RemoveCSSEquivalentToHTMLStyle(aNode.AsElement(),
aProperty, aProperty,
aAttribute, attribute,
&propertyValue, &propertyValue,
false); false);
// remove the node if it is a span or font, if its style attribute is // remove the node if it is a span or font, if its style attribute is

View File

@ -1422,9 +1422,9 @@ TextEditRules::CreateMozBR(nsIDOMNode* inParent,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// give it special moz attr // give it special moz attr
nsCOMPtr<nsIDOMElement> brElem = do_QueryInterface(brNode); nsCOMPtr<Element> brElem = do_QueryInterface(brNode);
if (brElem) { if (brElem) {
rv = mTextEditor->SetAttribute(brElem, NS_LITERAL_STRING("type"), rv = mTextEditor->SetAttribute(brElem, nsGkAtoms::type,
NS_LITERAL_STRING("_moz")); NS_LITERAL_STRING("_moz"));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} }

View File

@ -311,9 +311,9 @@ TextEditor::UpdateMetaCharset(nsIDOMDocument* aDocument,
} }
// set attribute to <original prefix> charset=text/html // set attribute to <original prefix> charset=text/html
nsCOMPtr<nsIDOMElement> metaElement = do_QueryInterface(metaNode); RefPtr<Element> metaElement = metaNode->AsElement();
MOZ_ASSERT(metaElement); MOZ_ASSERT(metaElement);
rv = EditorBase::SetAttribute(metaElement, NS_LITERAL_STRING("content"), rv = EditorBase::SetAttribute(metaElement, nsGkAtoms::content,
Substring(originalStart, start) + Substring(originalStart, start) +
charsetEquals + charsetEquals +
NS_ConvertASCIItoUTF16(aCharacterSet)); NS_ConvertASCIItoUTF16(aCharacterSet));
@ -1622,8 +1622,8 @@ TextEditor::GetDOMEventTarget()
nsresult nsresult
TextEditor::SetAttributeOrEquivalent(nsIDOMElement* aElement, TextEditor::SetAttributeOrEquivalent(Element* aElement,
const nsAString& aAttribute, nsIAtom* aAttribute,
const nsAString& aValue, const nsAString& aValue,
bool aSuppressTransaction) bool aSuppressTransaction)
{ {
@ -1631,8 +1631,8 @@ TextEditor::SetAttributeOrEquivalent(nsIDOMElement* aElement,
} }
nsresult nsresult
TextEditor::RemoveAttributeOrEquivalent(nsIDOMElement* aElement, TextEditor::RemoveAttributeOrEquivalent(Element* aElement,
const nsAString& aAttribute, nsIAtom* aAttribute,
bool aSuppressTransaction) bool aSuppressTransaction)
{ {
return EditorBase::RemoveAttribute(aElement, aAttribute); return EditorBase::RemoveAttribute(aElement, aAttribute);

View File

@ -63,14 +63,17 @@ public:
// nsIEditorMailSupport overrides // nsIEditorMailSupport overrides
NS_DECL_NSIEDITORMAILSUPPORT NS_DECL_NSIEDITORMAILSUPPORT
// Overrides of EditorBase interface methods // Overrides of EditorBase
NS_IMETHOD SetAttributeOrEquivalent(nsIDOMElement* aElement, virtual nsresult RemoveAttributeOrEquivalent(
const nsAString& aAttribute, Element* aElement,
const nsAString& aValue, nsIAtom* aAttribute,
bool aSuppressTransaction) override; bool aSuppressTransaction) override;
NS_IMETHOD RemoveAttributeOrEquivalent(nsIDOMElement* aElement, virtual nsresult SetAttributeOrEquivalent(Element* aElement,
const nsAString& aAttribute, nsIAtom* aAttribute,
bool aSuppressTransaction) override; const nsAString& aValue,
bool aSuppressTransaction) override;
using EditorBase::RemoveAttributeOrEquivalent;
using EditorBase::SetAttributeOrEquivalent;
NS_IMETHOD Init(nsIDOMDocument* aDoc, nsIContent* aRoot, NS_IMETHOD Init(nsIDOMDocument* aDoc, nsIContent* aRoot,
nsISelectionController* aSelCon, uint32_t aFlags, nsISelectionController* aSelCon, uint32_t aFlags,