зеркало из https://github.com/mozilla/pjs.git
CSS in Composer, step 1 ; b=77705, r=jfrancis, r=cmanske, sr=kin
This commit is contained in:
Родитель
738505d551
Коммит
e33a80b378
|
@ -20,7 +20,8 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ryan Cassin (rcassin@supernova.org)
|
||||
* Ryan Cassin <rcassin@supernova.org>
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -792,6 +793,77 @@ nsFontColorStateCommand::SetState(nsIEditorShell *aEditorShell, nsString& newSta
|
|||
return rv;
|
||||
}
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
nsHighlightColorStateCommand::nsHighlightColorStateCommand()
|
||||
: nsMultiStateCommand()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHighlightColorStateCommand::GetCurrentState(nsIEditorShell *aEditorShell, nsString& outStateString, PRBool& outMixed)
|
||||
{
|
||||
NS_ASSERTION(aEditorShell, "Need an editor shell here");
|
||||
|
||||
nsCOMPtr<nsIEditor> editor;
|
||||
aEditorShell->GetEditor(getter_AddRefs(editor));
|
||||
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(editor);
|
||||
if (!htmlEditor) return NS_ERROR_FAILURE;
|
||||
|
||||
return htmlEditor->GetHighlightColorState(&outMixed, outStateString);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHighlightColorStateCommand::SetState(nsIEditorShell *aEditorShell, nsString& newState)
|
||||
{
|
||||
NS_ASSERTION(aEditorShell, "Need an editor shell here");
|
||||
|
||||
nsCOMPtr<nsIEditor> editor;
|
||||
aEditorShell->GetEditor(getter_AddRefs(editor));
|
||||
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(editor);
|
||||
if (!htmlEditor) return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIAtom> fontAtom = getter_AddRefs(NS_NewAtom("font"));
|
||||
|
||||
if (!newState.Length() || newState.Equals(NS_LITERAL_STRING("normal"))) {
|
||||
rv = htmlEditor->RemoveInlineProperty(fontAtom, NS_LITERAL_STRING("bgcolor"));
|
||||
} else {
|
||||
rv = htmlEditor->SetCSSInlineProperty(fontAtom, NS_LITERAL_STRING("bgcolor"), newState);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHighlightColorStateCommand::IsCommandEnabled(const nsAReadableString & aCommandName, nsISupports *refCon, PRBool *outCmdEnabled)
|
||||
{
|
||||
nsCOMPtr<nsIEditorShell> editorShell = do_QueryInterface(refCon);
|
||||
*outCmdEnabled = PR_FALSE;
|
||||
if (editorShell && EditingHTML(editorShell))
|
||||
{
|
||||
nsCOMPtr<nsIEditor> editor;
|
||||
editorShell->GetEditor(getter_AddRefs(editor));
|
||||
PRBool useCSS;
|
||||
editor->IsCSSEnabled(&useCSS);
|
||||
|
||||
*outCmdEnabled = useCSS;
|
||||
}
|
||||
|
||||
nsresult rv = UpdateCommandState(aCommandName, refCon);
|
||||
if (NS_FAILED(rv)) {
|
||||
*outCmdEnabled = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ryan Cassin (rcassin@supernova.org)
|
||||
* Ryan Cassin <rcassin@supernova.org>
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -215,6 +216,19 @@ protected:
|
|||
virtual nsresult SetState(nsIEditorShell *aEditorShell, nsString& newState);
|
||||
};
|
||||
|
||||
class nsHighlightColorStateCommand : public nsMultiStateCommand
|
||||
{
|
||||
public:
|
||||
nsHighlightColorStateCommand();
|
||||
|
||||
protected:
|
||||
|
||||
virtual nsresult GetCurrentState(nsIEditorShell *aEditorShell, nsString& outStateString, PRBool& outMixed);
|
||||
virtual nsresult SetState(nsIEditorShell *aEditorShell, nsString& newState);
|
||||
NS_IMETHOD IsCommandEnabled(const nsAReadableString & aCommandName, nsISupports *aCommandRefCon, PRBool *_retval);
|
||||
|
||||
};
|
||||
|
||||
class nsFontColorStateCommand : public nsMultiStateCommand
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* Contributor(s):
|
||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
* Ryan Cassin <rcassin@supernova.org>
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -200,6 +201,7 @@ nsresult nsComposerController::RegisterComposerCommands(nsIControllerCommandMana
|
|||
NS_REGISTER_ONE_COMMAND(nsFontFaceStateCommand, "cmd_fontFace");
|
||||
NS_REGISTER_ONE_COMMAND(nsFontColorStateCommand, "cmd_fontColor");
|
||||
NS_REGISTER_ONE_COMMAND(nsBackgroundColorStateCommand, "cmd_backgroundColor");
|
||||
NS_REGISTER_ONE_COMMAND(nsHighlightColorStateCommand, "cmd_highlight");
|
||||
|
||||
NS_REGISTER_ONE_COMMAND(nsAlignCommand, "cmd_align");
|
||||
NS_REGISTER_ONE_COMMAND(nsRemoveStylesCommand, "cmd_removeStyles");
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -4982,3 +4983,14 @@ nsEditorShell::DoControllerCommand(const nsAReadableString& aCommand)
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditorShell::CSSPrefChangedCallback(PRBool aIsCSSPrefChecked)
|
||||
{
|
||||
nsresult err = NS_NOINTERFACE;
|
||||
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(mEditor);
|
||||
if (htmlEditor)
|
||||
{
|
||||
err = htmlEditor->SetCSSEnabled(aIsCSSPrefChecked);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* Copyright (C) 1999, Mozilla. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*/
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
@ -78,6 +79,14 @@ interface nsIEditor : nsISupports
|
|||
*/
|
||||
[noscript] void Init(in nsIDOMDocument doc, in nsIPresShellPtr shell, in nsIContentPtr aRoot, in nsISelectionController aSelCon, in unsigned long aFlags);
|
||||
|
||||
/** IsCSSEnabled answers a boolean which is true is the HTMLEditor has been
|
||||
* instantiated with CSS knowledge and if the CSS pref is currently checked
|
||||
*
|
||||
* @param aIsSet [OUT] true if CSS handled and enabled
|
||||
*/
|
||||
void IsCSSEnabled(out PRBool aIsSet);
|
||||
|
||||
void SetCSSEquivalentToHTMLStyle(in nsIDOMElement element, in DOMString sourceAttrName, in DOMString sourceAttrValue);
|
||||
/**
|
||||
* PostCreate should be called after Init, and is the time that the editor tells
|
||||
* its documentStateObservers that the document has been created.
|
||||
|
|
|
@ -514,6 +514,7 @@ interface nsIEditorShell : nsISupports
|
|||
wstring GetAlignment(out boolean mixed);
|
||||
|
||||
void ApplyStyleSheet(in wstring url);
|
||||
void CSSPrefChangedCallback(in boolean isCSSPrefChecked);
|
||||
|
||||
/** Set the display mode for editing
|
||||
* displayMode
|
||||
|
|
|
@ -76,6 +76,9 @@ interface nsIHTMLEditor : nsISupports
|
|||
* @param aValue if aAttribute is not null, the value of the attribute. May be null.
|
||||
* Example: aProperty="font", aAttribute="color", aValue="0x00FFFF"
|
||||
*/
|
||||
void SetCSSInlineProperty(in nsIAtom aProperty,
|
||||
in DOMString aAttribute,
|
||||
in DOMString aValue);
|
||||
void SetInlineProperty(in nsIAtom aProperty,
|
||||
in DOMString aAttribute,
|
||||
in DOMString aValue);
|
||||
|
@ -273,6 +276,14 @@ interface nsIHTMLEditor : nsISupports
|
|||
*/
|
||||
void GetBackgroundColorState(out boolean aMixed,out DOMString outColor);
|
||||
|
||||
/**
|
||||
* GetHighlightColorState returns what the highlight color of the selection.
|
||||
* @param aMixed True if there is more than one font color
|
||||
* @param outColor Color string. "" is returned for none.
|
||||
*/
|
||||
void GetHighlightColorState(out boolean aMixed,out DOMString outColor);
|
||||
wstring GetHighlightColor(out boolean mixed);
|
||||
|
||||
/**
|
||||
* GetListState returns what list type is in the selection.
|
||||
* @param aMixed True if there is more than one type of list, or
|
||||
|
@ -430,5 +441,8 @@ interface nsIHTMLEditor : nsISupports
|
|||
* @return aNodeList the linked nodes found
|
||||
*/
|
||||
nsISupportsArray GetLinkedObjects();
|
||||
|
||||
void SetCSSEnabled(in boolean aIsCSSPrefChecked);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "nsIEditProperty.h"
|
||||
#include "nsIParser.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
void
|
||||
ChangeCSSInlineStyleTxn::AppendDeclaration(nsAWritableString & aOutputString,
|
||||
|
@ -91,7 +92,9 @@ ChangeCSSInlineStyleTxn::ValueIncludes(const nsAReadableString &aValueList, cons
|
|||
}
|
||||
}
|
||||
else {
|
||||
if (!nsCRT::strcasecmp(value, start)) {
|
||||
if (!Compare(nsDependentString(value),
|
||||
nsDependentString(start),
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
|
@ -162,6 +165,8 @@ NS_IMETHODIMP ChangeCSSInlineStyleTxn::Init(nsIEditor *aEditor,
|
|||
mValue.Assign(aValue);
|
||||
mRemoveProperty = aRemoveProperty;
|
||||
mPropertyWasSet = PR_FALSE;
|
||||
mUndoAttributeWasSet = PR_FALSE;
|
||||
mRedoAttributeWasSet = PR_FALSE;
|
||||
mUndoValue.SetLength(0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -174,8 +179,13 @@ NS_IMETHODIMP ChangeCSSInlineStyleTxn::DoTransaction(void)
|
|||
nsresult result=NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
|
||||
PRUint32 length;
|
||||
result = GetInlineStyles(mElement, getter_AddRefs(cssDecl), &length);
|
||||
PRUint32 length = 0;
|
||||
nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles = do_QueryInterface(mElement);
|
||||
if (!inlineStyles) return NS_ERROR_NULL_POINTER;
|
||||
result = inlineStyles->GetStyle(getter_AddRefs(cssDecl));
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!cssDecl) return NS_ERROR_NULL_POINTER;
|
||||
result = cssDecl->GetLength(&length);
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
||||
nsAutoString newDeclString, propertyNameString, undoString, redoString;
|
||||
|
@ -343,21 +353,6 @@ NS_IMETHODIMP ChangeCSSInlineStyleTxn::GetTxnDescription(nsAWritableString& aStr
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ChangeCSSInlineStyleTxn::GetInlineStyles(nsIDOMElement *aElement,
|
||||
nsIDOMCSSStyleDeclaration **aCssDecl,
|
||||
PRUint32 *aLength)
|
||||
{
|
||||
if (!aElement || !aLength) return NS_ERROR_NULL_POINTER;
|
||||
*aLength = 0;
|
||||
nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles = do_QueryInterface(aElement);
|
||||
if (!inlineStyles) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = inlineStyles->GetStyle(aCssDecl);
|
||||
if (NS_FAILED(res) || !aCssDecl) return NS_ERROR_NULL_POINTER;
|
||||
(*aCssDecl)->GetLength(aLength);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// answers true if the CSS property accepts more than one value
|
||||
PRBool
|
||||
ChangeCSSInlineStyleTxn::AcceptsMoreThanOneValue(nsIAtom *aCSSProperty)
|
||||
|
|
|
@ -75,15 +75,6 @@ public:
|
|||
const nsAReadableString & aValue,
|
||||
PRBool aRemoveProperty);
|
||||
|
||||
/** get the specified inline styles (style attribute) for an element
|
||||
*
|
||||
* @param aElement [IN] the element node
|
||||
* @param aCssDecl [OUT] the CSS declaration corresponding to the style attr
|
||||
* @param aLength [OUT] the number of declarations in aCssDecl
|
||||
*/
|
||||
static nsresult GetInlineStyles(nsIDOMElement * aElement, nsIDOMCSSStyleDeclaration ** aCssDecl,
|
||||
PRUint32 * aLength);
|
||||
|
||||
/** returns true if the list of white-space separated values contains aValue
|
||||
*
|
||||
* @return true if the value is in the list of values
|
||||
|
@ -111,8 +102,8 @@ private:
|
|||
PRBool AcceptsMoreThanOneValue(nsIAtom * aCSSProperty);
|
||||
|
||||
/** remove a value from a list of white-space separated values
|
||||
* @param aValueList [IN] a list of white-space separated values
|
||||
* @param aValue [IN] the value to remove from the list
|
||||
* @param aValues [IN] a list of white-space separated values
|
||||
* @param aRemoveValue [IN] the value to remove from the list
|
||||
*/
|
||||
void RemoveValueFromListOfValues(nsAWritableString & aValues, const nsAReadableString & aRemoveValue);
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ REQUIRES = xpcom \
|
|||
gfx \
|
||||
widget \
|
||||
xuldoc \
|
||||
unicharutil \
|
||||
webbrwsr \
|
||||
$(NULL)
|
||||
|
||||
|
@ -65,6 +66,7 @@ CPPSRCS += \
|
|||
EditTxn.cpp \
|
||||
PlaceholderTxn.cpp \
|
||||
ChangeAttributeTxn.cpp \
|
||||
ChangeCSSInlineStyleTxn.cpp \
|
||||
CreateElementTxn.cpp \
|
||||
DeleteElementTxn.cpp \
|
||||
DeleteRangeTxn.cpp \
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -54,6 +55,7 @@
|
|||
|
||||
#ifndef MOZILLA_PLAINTEXT_EDITOR_ONLY
|
||||
#include "SetDocTitleTxn.h"
|
||||
#include "ChangeCSSInlineStyleTxn.h"
|
||||
#endif // MOZILLA_PLAINTEXT_EDITOR_ONLY
|
||||
|
||||
TransactionFactory::TransactionFactory()
|
||||
|
@ -83,6 +85,10 @@ TransactionFactory::GetNewTransaction(REFNSIID aTxnType, EditTxn **aResult)
|
|||
*aResult = new DeleteRangeTxn();
|
||||
else if (aTxnType.Equals(ChangeAttributeTxn::GetCID()))
|
||||
*aResult = new ChangeAttributeTxn();
|
||||
#ifndef MOZILLA_PLAINTEXT_EDITOR_ONLY
|
||||
else if (aTxnType.Equals(ChangeCSSInlineStyleTxn::GetCID()))
|
||||
*aResult = new ChangeCSSInlineStyleTxn();
|
||||
#endif // MOZILLA_PLAINTEXT_EDITOR_ONLY
|
||||
else if (aTxnType.Equals(SplitElementTxn::GetCID()))
|
||||
*aResult = new SplitElementTxn();
|
||||
else if (aTxnType.Equals(JoinElementTxn::GetCID()))
|
||||
|
|
|
@ -38,11 +38,13 @@ REQUIRES = xpcom \
|
|||
appshell \
|
||||
gfx \
|
||||
widget \
|
||||
webBrowser_core \
|
||||
unicharutil \
|
||||
webBrowser_core \
|
||||
$(NULL)
|
||||
|
||||
CPP_OBJS = \
|
||||
.\$(OBJDIR)\ChangeAttributeTxn.obj \
|
||||
.\$(OBJDIR)\ChangeCSSInlineStyleTxn.obj \
|
||||
.\$(OBJDIR)\CreateElementTxn.obj \
|
||||
.\$(OBJDIR)\DeleteElementTxn.obj \
|
||||
.\$(OBJDIR)\DeleteRangeTxn.obj \
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -71,6 +72,8 @@
|
|||
#include "nsIPlaintextEditor.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
#include "nsIDOMCSSStyleDeclaration.h"
|
||||
|
||||
#include "nsIFrame.h" // Needed by IME code
|
||||
|
||||
#include "nsICSSStyleSheet.h"
|
||||
|
@ -87,6 +90,7 @@
|
|||
#include "EditAggregateTxn.h"
|
||||
#include "PlaceholderTxn.h"
|
||||
#include "ChangeAttributeTxn.h"
|
||||
#include "ChangeCSSInlineStyleTxn.h"
|
||||
#include "CreateElementTxn.h"
|
||||
#include "InsertElementTxn.h"
|
||||
#include "DeleteElementTxn.h"
|
||||
|
@ -97,6 +101,7 @@
|
|||
#include "JoinElementTxn.h"
|
||||
#include "nsStyleSheetTxns.h"
|
||||
#include "IMETextTxn.h"
|
||||
#include "nsIEditProperty.h"
|
||||
|
||||
// included for nsEditor::CreateHTMLContent
|
||||
#include "nsIElementFactory.h"
|
||||
|
@ -1078,7 +1083,6 @@ nsEditor::SetAttribute(nsIDOMElement *aElement, const nsAReadableString & aAttri
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsEditor::GetAttributeValue(nsIDOMElement *aElement,
|
||||
const nsAReadableString & aAttribute,
|
||||
|
@ -2173,6 +2177,8 @@ nsEditor::CloneAttributes(nsIDOMNode *aDestNode, nsIDOMNode *aSourceNode)
|
|||
|
||||
if (!aDestNode || !aSourceNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
PRBool useCSS;
|
||||
IsCSSEnabled(&useCSS);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> destElement = do_QueryInterface(aDestNode);
|
||||
nsCOMPtr<nsIDOMElement> sourceElement = do_QueryInterface(aSourceNode);
|
||||
|
@ -2255,10 +2261,19 @@ nsEditor::CloneAttributes(nsIDOMNode *aDestNode, nsIDOMNode *aSourceNode)
|
|||
*/
|
||||
if (NS_SUCCEEDED(sourceAttribute->GetValue(sourceAttrValue)))
|
||||
{
|
||||
if (destInBody)
|
||||
SetAttribute(destElement, sourceAttrName, sourceAttrValue);
|
||||
else
|
||||
if (destInBody) {
|
||||
if (useCSS) {
|
||||
res = SetCSSEquivalentToHTMLStyle(destElement, sourceAttrName, sourceAttrValue);
|
||||
}
|
||||
else {
|
||||
SetAttribute(destElement, sourceAttrName, sourceAttrValue);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// only elements in BODY can carry a STYLE attribute
|
||||
// so there is no need to test the value of useCSS here
|
||||
destElement->SetAttribute(sourceAttrName, sourceAttrValue);
|
||||
}
|
||||
} else {
|
||||
// Do we ever get here?
|
||||
#if DEBUG_cmanske
|
||||
|
@ -5229,3 +5244,18 @@ nsEditor::CreateHTMLContent(const nsAReadableString& aTag, nsIContent** aContent
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsEditor::IsCSSEnabled(PRBool *aIsSet)
|
||||
{
|
||||
*aIsSet = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsEditor::SetCSSEquivalentToHTMLStyle(nsIDOMElement * aElement,
|
||||
const nsAReadableString & aAttribute,
|
||||
const nsAReadableString & aValue)
|
||||
{
|
||||
return SetAttribute(aElement, aAttribute, aValue);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -136,6 +137,7 @@ public:
|
|||
/* ------------ utility methods -------------- */
|
||||
NS_IMETHOD GetPresShell(nsIPresShell **aPS);
|
||||
void NotifyEditorObservers(void);
|
||||
|
||||
/* ------------ nsIEditor methods -------------- */
|
||||
NS_DECL_NSIEDITOR
|
||||
/* ------------ nsIEditorIMESupport methods -------------- */
|
||||
|
@ -501,7 +503,7 @@ public:
|
|||
/** from html rules code - migration in progress */
|
||||
static nsresult GetTagString(nsIDOMNode *aNode, nsAWritableString& outString);
|
||||
static nsCOMPtr<nsIAtom> GetTag(nsIDOMNode *aNode);
|
||||
static PRBool NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
|
||||
virtual PRBool NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
|
||||
static PRBool IsTextOrElementNode(nsIDOMNode *aNode);
|
||||
static PRBool IsTextNode(nsIDOMNode *aNode);
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -144,9 +145,37 @@ public:
|
|||
|
||||
// XXX: end temp code
|
||||
|
||||
/** CSS strings */
|
||||
static nsIAtom *cssBackgroundColor;
|
||||
static nsIAtom *cssBackgroundImage;
|
||||
static nsIAtom *cssBorder;
|
||||
static nsIAtom *cssCaptionSide;
|
||||
static nsIAtom *cssColor;
|
||||
static nsIAtom *cssFloat;
|
||||
static nsIAtom *cssFontFamily;
|
||||
static nsIAtom *cssFontSize;
|
||||
static nsIAtom *cssFontStyle;
|
||||
static nsIAtom *cssFontWeight;
|
||||
static nsIAtom *cssHeight;
|
||||
static nsIAtom *cssListStyleType;
|
||||
static nsIAtom *cssMarginLeft;
|
||||
static nsIAtom *cssMarginRight;
|
||||
static nsIAtom *cssTextAlign;
|
||||
static nsIAtom *cssTextDecoration;
|
||||
static nsIAtom *cssVerticalAlign;
|
||||
static nsIAtom *cssWhitespace;
|
||||
static nsIAtom *cssWidth;
|
||||
|
||||
|
||||
|
||||
static nsIAtom *cssPxUnit;
|
||||
static nsIAtom *cssEmUnit;
|
||||
static nsIAtom *cssCmUnit;
|
||||
static nsIAtom *cssPercentUnit;
|
||||
static nsIAtom *cssInUnit;
|
||||
static nsIAtom *cssMmUnit;
|
||||
static nsIAtom *cssPtUnit;
|
||||
static nsIAtom *cssPcUnit;
|
||||
static nsIAtom *cssExUnit;
|
||||
};
|
||||
|
||||
extern nsresult NS_NewEditProperty(nsIEditProperty **aResult);
|
||||
|
|
|
@ -34,7 +34,7 @@ REQUIRES = xpcom \
|
|||
dom \
|
||||
layout \
|
||||
locale \
|
||||
unicharutil \
|
||||
unicharutil \
|
||||
content \
|
||||
txmgr \
|
||||
htmlparser \
|
||||
|
@ -50,11 +50,12 @@ REQUIRES = xpcom \
|
|||
CPPSRCS = \
|
||||
nsEditProperty.cpp \
|
||||
nsHTMLDataTransfer.cpp \
|
||||
nsHTMLCSSUtils.cpp \
|
||||
nsHTMLEditor.cpp \
|
||||
nsHTMLEditorStyle.cpp \
|
||||
nsHTMLEditRules.cpp \
|
||||
nsHTMLEditUtils.cpp \
|
||||
nsHTMLURIRefObject.cpp \
|
||||
nsHTMLURIRefObject.cpp \
|
||||
nsTableEditor.cpp \
|
||||
nsWSRunObject.cpp \
|
||||
TypeInState.cpp \
|
||||
|
|
|
@ -36,12 +36,14 @@ REQUIRES = xpcom \
|
|||
pref \
|
||||
gfx \
|
||||
widget \
|
||||
unicharutil \
|
||||
webBrowser_core \
|
||||
$(NULL)
|
||||
|
||||
CPP_OBJS = \
|
||||
.\$(OBJDIR)\TypeInState.obj \
|
||||
.\$(OBJDIR)\nsEditProperty.obj \
|
||||
.\$(OBJDIR)\nsHTMLCSSUtils.obj \
|
||||
.\$(OBJDIR)\nsHTMLDataTransfer.obj \
|
||||
.\$(OBJDIR)\nsHTMLEditRules.obj \
|
||||
.\$(OBJDIR)\nsHTMLEditUtils.obj \
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -122,6 +123,37 @@ nsIAtom * nsIEditProperty::color;
|
|||
nsIAtom * nsIEditProperty::face;
|
||||
nsIAtom * nsIEditProperty::size;
|
||||
|
||||
nsIAtom * nsIEditProperty::cssBackgroundColor;
|
||||
nsIAtom * nsIEditProperty::cssBackgroundImage;
|
||||
nsIAtom * nsIEditProperty::cssBorder;
|
||||
nsIAtom * nsIEditProperty::cssCaptionSide;
|
||||
nsIAtom * nsIEditProperty::cssColor;
|
||||
nsIAtom * nsIEditProperty::cssFloat;
|
||||
nsIAtom * nsIEditProperty::cssFontFamily;
|
||||
nsIAtom * nsIEditProperty::cssFontSize;
|
||||
nsIAtom * nsIEditProperty::cssFontStyle;
|
||||
nsIAtom * nsIEditProperty::cssFontWeight;
|
||||
nsIAtom * nsIEditProperty::cssHeight;
|
||||
nsIAtom * nsIEditProperty::cssListStyleType;
|
||||
nsIAtom * nsIEditProperty::cssMarginLeft;
|
||||
nsIAtom * nsIEditProperty::cssMarginRight;
|
||||
nsIAtom * nsIEditProperty::cssTextAlign;
|
||||
nsIAtom * nsIEditProperty::cssTextDecoration;
|
||||
nsIAtom * nsIEditProperty::cssVerticalAlign;
|
||||
nsIAtom * nsIEditProperty::cssWhitespace;
|
||||
nsIAtom * nsIEditProperty::cssWidth;
|
||||
|
||||
|
||||
nsIAtom * nsIEditProperty::cssPxUnit;
|
||||
nsIAtom * nsIEditProperty::cssEmUnit;
|
||||
nsIAtom * nsIEditProperty::cssCmUnit;
|
||||
nsIAtom * nsIEditProperty::cssPercentUnit;
|
||||
nsIAtom * nsIEditProperty::cssInUnit;
|
||||
nsIAtom * nsIEditProperty::cssMmUnit;
|
||||
nsIAtom * nsIEditProperty::cssPtUnit;
|
||||
nsIAtom * nsIEditProperty::cssPcUnit;
|
||||
nsIAtom * nsIEditProperty::cssExUnit;
|
||||
|
||||
// special
|
||||
nsString * nsIEditProperty::allProperties;
|
||||
|
||||
|
@ -227,6 +259,36 @@ nsEditProperty::nsEditProperty()
|
|||
nsIEditProperty::face = NS_NewAtom("face");
|
||||
nsIEditProperty::size = NS_NewAtom("size");
|
||||
|
||||
nsIEditProperty::cssBackgroundColor = NS_NewAtom("background-color");
|
||||
nsIEditProperty::cssBackgroundImage = NS_NewAtom("background-image");
|
||||
nsIEditProperty::cssBorder = NS_NewAtom("border");
|
||||
nsIEditProperty::cssCaptionSide = NS_NewAtom("caption-side");
|
||||
nsIEditProperty::cssColor = NS_NewAtom("color");
|
||||
nsIEditProperty::cssFloat = NS_NewAtom("float");
|
||||
nsIEditProperty::cssFontFamily = NS_NewAtom("font-family");
|
||||
nsIEditProperty::cssFontSize = NS_NewAtom("font-size");
|
||||
nsIEditProperty::cssFontStyle = NS_NewAtom("font-style");
|
||||
nsIEditProperty::cssFontWeight = NS_NewAtom("font-weight");
|
||||
nsIEditProperty::cssHeight = NS_NewAtom("height");
|
||||
nsIEditProperty::cssListStyleType = NS_NewAtom("list-style-type");
|
||||
nsIEditProperty::cssMarginRight = NS_NewAtom("margin-right");
|
||||
nsIEditProperty::cssMarginLeft = NS_NewAtom("margin-left");
|
||||
nsIEditProperty::cssTextAlign = NS_NewAtom("text-align");
|
||||
nsIEditProperty::cssTextDecoration = NS_NewAtom("text-decoration");
|
||||
nsIEditProperty::cssVerticalAlign = NS_NewAtom("vertical-align");
|
||||
nsIEditProperty::cssWhitespace = NS_NewAtom("white-space");
|
||||
nsIEditProperty::cssWidth = NS_NewAtom("width");
|
||||
|
||||
|
||||
nsIEditProperty::cssPxUnit = NS_NewAtom("px");
|
||||
nsIEditProperty::cssEmUnit = NS_NewAtom("em");
|
||||
nsIEditProperty::cssCmUnit = NS_NewAtom("cm");
|
||||
nsIEditProperty::cssPercentUnit = NS_NewAtom("%");
|
||||
nsIEditProperty::cssInUnit = NS_NewAtom("in");
|
||||
nsIEditProperty::cssMmUnit = NS_NewAtom("mm");
|
||||
nsIEditProperty::cssPtUnit = NS_NewAtom("pt");
|
||||
nsIEditProperty::cssPcUnit = NS_NewAtom("pc");
|
||||
nsIEditProperty::cssExUnit = NS_NewAtom("ex");
|
||||
|
||||
// special
|
||||
if ( (nsIEditProperty::allProperties = new nsString) != nsnull )
|
||||
|
@ -307,6 +369,36 @@ nsEditProperty::~nsEditProperty()
|
|||
NS_IF_RELEASE(nsIEditProperty::face);
|
||||
NS_IF_RELEASE(nsIEditProperty::size);
|
||||
|
||||
NS_IF_RELEASE(nsIEditProperty::cssBackgroundColor);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssBackgroundImage);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssBorder);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssCaptionSide);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssColor);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssFloat);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssFontFamily);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssFontSize);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssFontStyle);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssFontWeight);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssHeight);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssListStyleType);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssMarginRight);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssMarginLeft);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssTextAlign);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssTextDecoration);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssVerticalAlign);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssWhitespace);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssWidth);
|
||||
|
||||
NS_IF_RELEASE(nsIEditProperty::cssPxUnit);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssEmUnit);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssCmUnit);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssPercentUnit);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssInUnit);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssMmUnit);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssPtUnit);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssPcUnit);
|
||||
NS_IF_RELEASE(nsIEditProperty::cssExUnit);
|
||||
|
||||
// special
|
||||
if (nsIEditProperty::allProperties) {
|
||||
delete (nsIEditProperty::allProperties);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,389 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Original Author: Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsHTMLCSSUtils_h__
|
||||
#define nsHTMLCSSUtils_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIDOMViewCSS.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIHTMLEditor.h"
|
||||
#include "ChangeCSSInlineStyleTxn.h"
|
||||
#include "nsIEditProperty.h"
|
||||
#include "nsIDOMCSSStyleDeclaration.h"
|
||||
|
||||
#define SPECIFIED_STYLE_TYPE 1
|
||||
#define COMPUTED_STYLE_TYPE 2
|
||||
|
||||
class nsHTMLEditor;
|
||||
|
||||
typedef void (*nsProcessValueFunc)(nsAReadableString * aInputString, nsAWritableString & aOutputString,
|
||||
const char * aDefaultValueString,
|
||||
const char * aPrependString, const char* aAppendString);
|
||||
|
||||
class nsHTMLCSSUtils
|
||||
{
|
||||
public:
|
||||
nsHTMLCSSUtils();
|
||||
~nsHTMLCSSUtils();
|
||||
|
||||
enum nsCSSEditableProperty {
|
||||
eCSSEditableProperty_NONE=0,
|
||||
eCSSEditableProperty_background_color,
|
||||
eCSSEditableProperty_background_image,
|
||||
eCSSEditableProperty_border,
|
||||
eCSSEditableProperty_caption_side,
|
||||
eCSSEditableProperty_color,
|
||||
eCSSEditableProperty_float,
|
||||
eCSSEditableProperty_font_family,
|
||||
eCSSEditableProperty_font_size,
|
||||
eCSSEditableProperty_font_style,
|
||||
eCSSEditableProperty_font_weight,
|
||||
eCSSEditableProperty_height,
|
||||
eCSSEditableProperty_list_style_type,
|
||||
eCSSEditableProperty_margin_left,
|
||||
eCSSEditableProperty_margin_right,
|
||||
eCSSEditableProperty_text_align,
|
||||
eCSSEditableProperty_text_decoration,
|
||||
eCSSEditableProperty_vertical_align,
|
||||
eCSSEditableProperty_whitespace,
|
||||
eCSSEditableProperty_width
|
||||
};
|
||||
|
||||
|
||||
struct CSSEquivTable {
|
||||
nsCSSEditableProperty cssProperty;
|
||||
nsProcessValueFunc processValueFunctor;
|
||||
const char * defaultValue;
|
||||
const char * prependValue;
|
||||
const char * appendValue;
|
||||
PRBool gettable;
|
||||
};
|
||||
|
||||
public:
|
||||
nsresult Init(nsHTMLEditor * aEditor);
|
||||
|
||||
/** answers true if the given combination element_name/attribute_name
|
||||
* has a CSS equivalence in this implementation
|
||||
*
|
||||
* @return a boolean saying if the tag/attribute has a css equiv
|
||||
* @param aNode [IN] a DOM node
|
||||
* @param aProperty [IN] an atom containing a HTML tag name
|
||||
* @param aAttribute [IN] a string containing the name of a HTML attribute carried by the element above
|
||||
*/
|
||||
PRBool IsCSSEditableProperty(nsIDOMNode * aNode, nsIAtom * aProperty, const nsAReadableString * aAttribute);
|
||||
|
||||
/** adds/remove a CSS declaration to the STYLE atrribute carried by a given element
|
||||
*
|
||||
* @param aElement [IN] a DOM element
|
||||
* @param aProperty [IN] an atom containing the CSS property to set
|
||||
* @param aValue [IN] a string containing the value of the CSS property
|
||||
*/
|
||||
nsresult SetCSSProperty(nsIDOMElement * aElement, nsIAtom * aProperty,
|
||||
const nsAReadableString & aValue);
|
||||
nsresult RemoveCSSProperty(nsIDOMElement * aElement, nsIAtom * aProperty,
|
||||
const nsAReadableString & aPropertyValue);
|
||||
|
||||
/** gets the specified/computed style value of a CSS property for a given node (or its element
|
||||
* ancestor if it is not an element)
|
||||
*
|
||||
* @param aNode [IN] a DOM node
|
||||
* @param aProperty [IN] an atom containing the CSS property to get
|
||||
* @param aPropertyValue [OUT] the retrieved value of the property
|
||||
*/
|
||||
nsresult GetSpecifiedProperty(nsIDOMNode *aNode, nsIAtom *aProperty,
|
||||
nsAWritableString & aValue);
|
||||
nsresult GetComputedProperty(nsIDOMNode *aNode, nsIAtom *aProperty,
|
||||
nsAWritableString & aValue);
|
||||
|
||||
/** Removes a CSS property from the specified declarations in STYLE attribute
|
||||
** and removes the node if it is an useless span
|
||||
*
|
||||
* @param aNode [IN] the specific node we want to remove a style from
|
||||
* @param aProperty [IN] the CSS property atom to remove
|
||||
* @param aPropertyValue [IN] the value of the property we have to rremove if the property
|
||||
* accepts more than one value
|
||||
*/
|
||||
nsresult RemoveCSSInlineStyle(nsIDOMNode * aNode, nsIAtom * aProperty, nsAReadableString & aPropertyValue);
|
||||
|
||||
/** Answers true is the property can be removed by setting a "none" CSS value
|
||||
* on a node
|
||||
*
|
||||
* @return a boolean saying if the property can be remove by setting a "none" value
|
||||
* @param aProperty [IN] an atom containing a CSS property
|
||||
* @param aAttribute [IN] pointer to an attribute name or null if this information is irrelevant
|
||||
*/
|
||||
PRBool IsCSSInvertable(nsIAtom * aProperty, const nsAReadableString * aAttribute);
|
||||
|
||||
/** Get the default browser background color if we need it for GetCSSBackgroundColorState
|
||||
*
|
||||
* @param aColor [OUT] the default color as it is defined in prefs
|
||||
*/
|
||||
nsresult GetDefaultBackgroundColor(nsAWritableString & aColor);
|
||||
|
||||
/** Get the default length unit used for CSS Indent/Outdent
|
||||
*
|
||||
* @param aLengthUnit [OUT] the default length unit as it is defined in prefs
|
||||
*/
|
||||
nsresult GetDefaultLengthUnit(nsAWritableString & aLengthUnit);
|
||||
|
||||
/** asnwers true if the element aElement carries an ID or a class
|
||||
*
|
||||
* @param aElement [IN] a DOM element
|
||||
* @param aReturn [OUT] the boolean answer
|
||||
*/
|
||||
nsresult HasClassOrID(nsIDOMElement * aElement, PRBool & aReturn);
|
||||
|
||||
/** returns the list of values for the CSS equivalences to
|
||||
* the passed HTML style for the passed node
|
||||
*
|
||||
* @param aNode [IN] a DOM node
|
||||
* @param aHTMLProperty [IN] an atom containing an HTML property
|
||||
* @param aAttribute [IN] a pointer to an attribute name or nsnull if irrelevant
|
||||
* @param aValueString [OUT] the list of css values
|
||||
* @param aStyleType [IN] SPECIFIED_STYLE_TYPE to query the specified style values
|
||||
COMPUTED_STYLE_TYPE to query the computed style values
|
||||
*/
|
||||
nsresult GetCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode * aNode,
|
||||
nsIAtom * aHTMLProperty,
|
||||
const nsAReadableString * aAttribute,
|
||||
nsAWritableString & aValueString,
|
||||
PRUint8 aStyleType);
|
||||
|
||||
/** Does the node aNode (or his parent if it is not an element node) carries
|
||||
* the CSS equivalent styles to the HTML style for this node ?
|
||||
*
|
||||
* @param aNode [IN] a DOM node
|
||||
* @param aHTMLProperty [IN] an atom containing an HTML property
|
||||
* @param aAttribute [IN] a pointer to an attribute name or nsnull 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 values (out)
|
||||
* @param aStyleType [IN] SPECIFIED_STYLE_TYPE to query the specified style values
|
||||
COMPUTED_STYLE_TYPE to query the computed style values
|
||||
*/
|
||||
nsresult IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode * aNode,
|
||||
nsIAtom * aHTMLProperty,
|
||||
const nsAReadableString * aAttribute,
|
||||
PRBool & aIsSet,
|
||||
nsAWritableString & aValueString,
|
||||
PRUint8 aStyleType);
|
||||
|
||||
/** Adds to the node the CSS inline styles equivalent to the HTML style
|
||||
* and return the number of CSS properties set by the call
|
||||
*
|
||||
* @param aNode [IN] a DOM node
|
||||
* @param aHTMLProperty [IN] an atom containing an HTML property
|
||||
* @param aAttribute [IN] a pointer to an attribute name or nsnull if irrelevant
|
||||
* @param aValue [IN] the attribute value
|
||||
* @param aCount [OUT] the number of CSS properties set by the call
|
||||
*/
|
||||
nsresult SetCSSEquivalentToHTMLStyle(nsIDOMNode * aNode,
|
||||
nsIAtom * aHTMLProperty,
|
||||
const nsAReadableString * aAttribute,
|
||||
const nsAReadableString * aValue,
|
||||
PRInt32 * aCount);
|
||||
|
||||
/** removes from the node the CSS inline styles equivalent to the HTML style
|
||||
*
|
||||
* @param aNode [IN] a DOM node
|
||||
* @param aHTMLProperty [IN] an atom containing an HTML property
|
||||
* @param aAttribute [IN] a pointer to an attribute name or nsnull if irrelevant
|
||||
* @param aValue [IN] the attribute value
|
||||
*/
|
||||
nsresult RemoveCSSEquivalentToHTMLStyle(nsIDOMNode * aNode,
|
||||
nsIAtom *aHTMLProperty,
|
||||
const nsAReadableString *aAttribute,
|
||||
const nsAReadableString *aValue);
|
||||
|
||||
/** parses a "xxxx.xxxxxuuu" string where x is a digit and u an alpha char
|
||||
* we need such a parser because nsIDOMCSSStyleDeclaration::GetPropertyCSSValue() is not
|
||||
* implemented
|
||||
*
|
||||
* @param aString [IN] input string to parse
|
||||
* @param aValue [OUT] numeric part
|
||||
* @param aUnit [OUT] unit part
|
||||
*/
|
||||
void ParseLength(nsAReadableString & aString, float * aValue, nsIAtom ** aUnit);
|
||||
|
||||
/** sets the mIsCSSPrefChecked private member ; used as callback from observer when
|
||||
* the css pref state is changed
|
||||
*
|
||||
* @param aIsCSSPrefChecked [IN] the new boolean state for the pref
|
||||
*/
|
||||
nsresult SetCSSEnabled(PRBool aIsCSSPrefChecked);
|
||||
|
||||
/** retrieves the mIsCSSPrefChecked private member, true if the css pref is checked,
|
||||
* false if it is not
|
||||
*
|
||||
* @return the boolean value of the css pref
|
||||
*/
|
||||
PRBool IsCSSPrefChecked();
|
||||
|
||||
/** ElementsSameStyle compares two elements and checks if they have the same
|
||||
* specified CSS declarations in the STYLE attribute
|
||||
* The answer is always false if at least one of them carries an ID or a class
|
||||
*
|
||||
* @return true if the two elements are considered to have same styles
|
||||
* @param aFirstNode [IN] a DOM node
|
||||
* @param aSecondNode [IN] a DOM node
|
||||
*/
|
||||
PRBool ElementsSameStyle(nsIDOMNode *aFirstNode, nsIDOMNode *aSecondNode);
|
||||
|
||||
/** get the specified inline styles (style attribute) for an element
|
||||
*
|
||||
* @param aElement [IN] the element node
|
||||
* @param aCssDecl [OUT] the CSS declaration corresponding to the style attr
|
||||
* @param aLength [OUT] the number of declarations in aCssDecl
|
||||
*/
|
||||
nsresult GetInlineStyles(nsIDOMElement * aElement, nsIDOMCSSStyleDeclaration ** aCssDecl,
|
||||
PRUint32 * aLength);
|
||||
|
||||
/** returns aNode itself if it is an element node, or the first ancestors being an element
|
||||
* node if aNode is not one itself
|
||||
*
|
||||
* @param aNode [IN] a node
|
||||
* @param aElement [OUT] the deepest element node containing aNode (possibly aNode itself)
|
||||
*/
|
||||
nsresult GetElementContainerOrSelf(nsIDOMNode * aNode, nsIDOMElement ** aElement);
|
||||
|
||||
private:
|
||||
|
||||
/** retrieves the css property atom from an enum
|
||||
*
|
||||
* @param aProperty [IN] the enum value for the property
|
||||
* @param aAtom [OUT] the corresponding atom
|
||||
*/
|
||||
void GetCSSPropertyAtom(nsCSSEditableProperty aProperty, nsIAtom ** aAtom);
|
||||
|
||||
/** retrieves the CSS declarations equivalent to a HTML style value for
|
||||
* a given equivalence table
|
||||
*
|
||||
* @param aPropertyArray [OUT] the array of css properties
|
||||
* @param aValueArray [OUT] the array of values for the css properties above
|
||||
* @param aEquivTable [IN] the equivalence table
|
||||
* @param aValue [IN] the HTML style value
|
||||
* @param aGetOrRemoveRequest [IN] a boolean value being true if the call to the current method
|
||||
* is made for GetCSSEquivalentToHTMLInlineStyleSet or
|
||||
* RemoveCSSEquivalentToHTMLInlineStyleSet
|
||||
*/
|
||||
|
||||
void BuildCSSDeclarations(nsVoidArray & aPropertyArray,
|
||||
nsStringArray & cssValueArray,
|
||||
const CSSEquivTable * aEquivTable,
|
||||
const nsAReadableString * aValue,
|
||||
PRBool aGetOrRemoveRequest);
|
||||
|
||||
/** retrieves the CSS declarations equivalent to the given HTML property/attribute/value
|
||||
* for a given node
|
||||
*
|
||||
* @param aNode [IN] the DOM node
|
||||
* @param aHTMLProperty [IN] an atom containing an HTML property
|
||||
* @param aAttribute [IN] a pointer to an attribute name or nsnull if irrelevant
|
||||
* @param aValue [IN] the attribute value
|
||||
* @param aPropertyArray [OUT] the array of css properties
|
||||
* @param aValueArray [OUT] the array of values for the css properties above
|
||||
* @param aGetOrRemoveRequest [IN] a boolean value being true if the call to the current method
|
||||
* is made for GetCSSEquivalentToHTMLInlineStyleSet or
|
||||
* RemoveCSSEquivalentToHTMLInlineStyleSet
|
||||
*/
|
||||
void GenerateCSSDeclarationsFromHTMLStyle(nsIDOMNode * aNode,
|
||||
nsIAtom * aHTMLProperty,
|
||||
const nsAReadableString *aAttribute,
|
||||
const nsAReadableString *aValue,
|
||||
nsVoidArray & aPropertyArray,
|
||||
nsStringArray & aValueArray,
|
||||
PRBool aGetOrRemoveRequest);
|
||||
|
||||
/** Gets the default DOMView for a given node
|
||||
*
|
||||
* @param aNode the node we want the default DOMView for
|
||||
* @param aViewCSS [OUT] the default DOMViewCSS
|
||||
*/
|
||||
nsresult GetDefaultViewCSS(nsIDOMNode * aNode, nsIDOMViewCSS ** aViewCSS);
|
||||
|
||||
/** creates a Transaction for setting or removing a css property
|
||||
*
|
||||
* @param aElement [IN] a DOM element
|
||||
* @param aProperty [IN] a CSS property
|
||||
* @param aValue [IN] the value to remove for this CSS property or the empty string if irrelevant
|
||||
* @param aTxn [OUT] the created transaction
|
||||
* @param aRemoveProperty [IN] true if we create a "remove" transaction, false for a "set"
|
||||
*/
|
||||
nsresult CreateCSSPropertyTxn(nsIDOMElement * aElement,
|
||||
nsIAtom * aProperty,
|
||||
const nsAReadableString & aValue,
|
||||
ChangeCSSInlineStyleTxn ** aTxn,
|
||||
PRBool aRemoveProperty);
|
||||
|
||||
/** back-end for GetSpecifiedProperty and GetComputedProperty
|
||||
*
|
||||
* @param aNode [IN] a DOM node
|
||||
* @param aProperty [IN] a CSS property
|
||||
* @param aValue [OUT] the retrieved value for this property
|
||||
* @param aViewCSS [IN] the ViewCSS we need in case we query computed styles
|
||||
* @param aStyleType [IN] SPECIFIED_STYLE_TYPE to query the specified style values
|
||||
COMPUTED_STYLE_TYPE to query the computed style values
|
||||
*/
|
||||
nsresult GetCSSInlinePropertyBase(nsIDOMNode * aNode, nsIAtom * aProperty,
|
||||
nsAWritableString & aValue,
|
||||
nsIDOMViewCSS * aViewCSS,
|
||||
PRUint8 aStyleType);
|
||||
|
||||
|
||||
private:
|
||||
nsHTMLEditor *mHTMLEditor;
|
||||
PRBool mIsCSSPrefChecked;
|
||||
|
||||
};
|
||||
|
||||
nsresult NS_NewHTMLCSSUtils(nsHTMLCSSUtils** aInstancePtrResult);
|
||||
|
||||
#define NS_EDITOR_INDENT_INCREMENT_IN 0.4134f
|
||||
#define NS_EDITOR_INDENT_INCREMENT_CM 1.05f
|
||||
#define NS_EDITOR_INDENT_INCREMENT_MM 10.5f
|
||||
#define NS_EDITOR_INDENT_INCREMENT_PT 29.76f
|
||||
#define NS_EDITOR_INDENT_INCREMENT_PC 2.48f
|
||||
#define NS_EDITOR_INDENT_INCREMENT_EM 3
|
||||
#define NS_EDITOR_INDENT_INCREMENT_EX 6
|
||||
#define NS_EDITOR_INDENT_INCREMENT_PX 40
|
||||
#define NS_EDITOR_INDENT_INCREMENT_PERCENT 4
|
||||
|
||||
#endif /* nsHTMLCSSUtils_h__ */
|
|
@ -70,6 +70,7 @@
|
|||
#include "nsIPresShell.h"
|
||||
#include "nsLayoutCID.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsIDOMNamedNodeMap.h"
|
||||
|
||||
#include "nsEditorUtils.h"
|
||||
#include "nsWSRunObject.h"
|
||||
|
@ -716,6 +717,45 @@ nsHTMLEditRules::GetAlignment(PRBool *aMixed, nsIHTMLEditor::EAlignment *aAlign)
|
|||
|
||||
if (!nodeToExamine) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRBool useCSS;
|
||||
mHTMLEditor->IsCSSEnabled(&useCSS);
|
||||
nsAutoString typeAttrName(NS_LITERAL_STRING("align"));
|
||||
nsIAtom *dummyProperty = nsnull;
|
||||
if (useCSS && mHTMLEditor->mHTMLCSSUtils->IsCSSEditableProperty(nodeToExamine, dummyProperty, &typeAttrName))
|
||||
{
|
||||
// we are in CSS mode and we know how to align this element with CSS
|
||||
nsAutoString value;
|
||||
// let's get the value(s) of text-align or margin-left/margin-right
|
||||
mHTMLEditor->mHTMLCSSUtils->GetCSSEquivalentToHTMLInlineStyleSet(nodeToExamine,
|
||||
dummyProperty,
|
||||
&typeAttrName,
|
||||
value,
|
||||
COMPUTED_STYLE_TYPE);
|
||||
if (value.Equals(NS_LITERAL_STRING("center")) ||
|
||||
value.Equals(NS_LITERAL_STRING("-moz-center")) ||
|
||||
value.Equals(NS_LITERAL_STRING("auto auto")))
|
||||
{
|
||||
*aAlign = nsIHTMLEditor::eCenter;
|
||||
return NS_OK;
|
||||
}
|
||||
else if (value.Equals(NS_LITERAL_STRING("right")) ||
|
||||
value.Equals(NS_LITERAL_STRING("-moz-right")) ||
|
||||
value.Equals(NS_LITERAL_STRING("auto 0px")))
|
||||
{
|
||||
*aAlign = nsIHTMLEditor::eRight;
|
||||
return NS_OK;
|
||||
}
|
||||
else if (value.Equals(NS_LITERAL_STRING("justify")))
|
||||
{
|
||||
*aAlign = nsIHTMLEditor::eJustify;
|
||||
return NS_OK;
|
||||
}
|
||||
else {
|
||||
*aAlign = nsIHTMLEditor::eLeft;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// check up the ladder for divs with alignment
|
||||
nsCOMPtr<nsIDOMNode> temp = nodeToExamine;
|
||||
PRBool isFirstNodeToExamine = PR_TRUE;
|
||||
|
@ -734,7 +774,6 @@ nsHTMLEditRules::GetAlignment(PRBool *aMixed, nsIHTMLEditor::EAlignment *aAlign)
|
|||
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(nodeToExamine);
|
||||
if (elem)
|
||||
{
|
||||
nsAutoString typeAttrName(NS_LITERAL_STRING("align"));
|
||||
nsAutoString typeAttrVal;
|
||||
res = elem->GetAttribute(typeAttrName, typeAttrVal);
|
||||
ToLowerCase(typeAttrVal);
|
||||
|
@ -787,6 +826,8 @@ nsHTMLEditRules::GetIndentState(PRBool *aCanIndent, PRBool *aCanOutdent)
|
|||
PRUint32 listCount;
|
||||
PRInt32 i;
|
||||
arrayOfNodes->Count(&listCount);
|
||||
PRBool useCSS;
|
||||
mHTMLEditor->IsCSSEnabled(&useCSS);
|
||||
for (i=(PRInt32)listCount-1; i>=0; i--)
|
||||
{
|
||||
nsCOMPtr<nsISupports> isupports = dont_AddRef(arrayOfNodes->ElementAt(i));
|
||||
|
@ -799,6 +840,22 @@ nsHTMLEditRules::GetIndentState(PRBool *aCanIndent, PRBool *aCanOutdent)
|
|||
*aCanOutdent = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
else if (useCSS) {
|
||||
// we are in CSS mode, indentation is done using the margin-left property
|
||||
nsAutoString value;
|
||||
// retrieve its specified value
|
||||
mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(curNode, nsIEditProperty::cssMarginLeft, value);
|
||||
float f;
|
||||
nsIAtom * unit;
|
||||
// get its number part and its unit
|
||||
mHTMLEditor->mHTMLCSSUtils->ParseLength(value, &f, &unit);
|
||||
NS_IF_RELEASE(unit);
|
||||
// if the number part is strictly positive, outdent is possible
|
||||
if (0 < f) {
|
||||
*aCanOutdent = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!*aCanOutdent)
|
||||
|
@ -1043,6 +1100,8 @@ nsHTMLEditRules::WillInsertText(PRInt32 aAction,
|
|||
{
|
||||
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
|
||||
|
||||
if (inString->IsEmpty() && (aAction != kInsertTextIME))
|
||||
{
|
||||
// HACK: this is a fix for bug 19395
|
||||
|
@ -1537,6 +1596,7 @@ nsHTMLEditRules::WillDeleteSelection(nsISelection *aSelection,
|
|||
}
|
||||
|
||||
// block parents the same?
|
||||
|
||||
if (mHTMLEditor->HasSameBlockNodeParent(startNode, priorNode))
|
||||
{
|
||||
// is prior node a text node?
|
||||
|
@ -2342,6 +2402,7 @@ nsHTMLEditRules::DeleteNonTableElements(nsIDOMNode *aNode)
|
|||
children->Item(j,getter_AddRefs(node));
|
||||
res = DeleteNonTableElements(node);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2887,6 +2948,22 @@ nsHTMLEditRules::DidMakeBasicBlock(nsISelection *aSelection,
|
|||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillIndent(nsISelection *aSelection, PRBool *aCancel, PRBool * aHandled)
|
||||
{
|
||||
PRBool useCSS;
|
||||
nsresult res;
|
||||
mHTMLEditor->IsCSSEnabled(&useCSS);
|
||||
|
||||
if (useCSS) {
|
||||
res = WillCSSIndent(aSelection, aCancel, aHandled);
|
||||
}
|
||||
else {
|
||||
res = WillHTMLIndent(aSelection, aCancel, aHandled);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillCSSIndent(nsISelection *aSelection, PRBool *aCancel, PRBool * aHandled)
|
||||
{
|
||||
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
|
@ -2940,6 +3017,151 @@ nsHTMLEditRules::WillIndent(nsISelection *aSelection, PRBool *aCancel, PRBool *
|
|||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
// if nothing visible in list, make an empty block
|
||||
if (ListIsEmptyLine(arrayOfNodes))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> parent, theBlock;
|
||||
PRInt32 offset;
|
||||
nsAutoString quoteType(NS_LITERAL_STRING("div"));
|
||||
// get selection location
|
||||
res = mHTMLEditor->GetStartNodeAndOffset(aSelection, address_of(parent), &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// make sure we can put a block here
|
||||
res = SplitAsNeeded("eType, address_of(parent), &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mHTMLEditor->CreateNode(quoteType, parent, offset, getter_AddRefs(theBlock));
|
||||
if (NS_FAILED(res)) return res;
|
||||
// remember our new block for postprocessing
|
||||
mNewBlock = theBlock;
|
||||
RelativeChangeIndentation(theBlock, +1);
|
||||
// delete anything that was in the list of nodes
|
||||
nsCOMPtr<nsISupports> isupports = dont_AddRef(arrayOfNodes->ElementAt(0));
|
||||
nsCOMPtr<nsIDOMNode> curNode;
|
||||
while (isupports)
|
||||
{
|
||||
curNode = do_QueryInterface(isupports);
|
||||
res = mHTMLEditor->DeleteNode(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = arrayOfNodes->RemoveElementAt(0);
|
||||
if (NS_FAILED(res)) return res;
|
||||
isupports = dont_AddRef(arrayOfNodes->ElementAt(0));
|
||||
}
|
||||
// put selection in new block
|
||||
res = aSelection->Collapse(theBlock,0);
|
||||
selectionResetter.Abort(); // to prevent selection reseter from overriding us.
|
||||
*aHandled = PR_TRUE;
|
||||
return res;
|
||||
}
|
||||
// Next we detect all the transitions in the array, where a transition
|
||||
// means that adjacent nodes in the array don't have the same parent.
|
||||
|
||||
nsVoidArray transitionList;
|
||||
res = MakeTransitionList(arrayOfNodes, &transitionList);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// Ok, now go through all the nodes and put them in a blockquote,
|
||||
// or whatever is appropriate. Wohoo!
|
||||
PRInt32 i;
|
||||
nsCOMPtr<nsIDOMNode> curParent;
|
||||
nsCOMPtr<nsIDOMNode> curQuote;
|
||||
nsCOMPtr<nsIDOMNode> curList;
|
||||
PRUint32 listCount;
|
||||
arrayOfNodes->Count(&listCount);
|
||||
for (i=0; i<(PRInt32)listCount; i++)
|
||||
{
|
||||
// here's where we actually figure out what to do
|
||||
nsCOMPtr<nsISupports> isupports = dont_AddRef(arrayOfNodes->ElementAt(i));
|
||||
nsCOMPtr<nsIDOMNode> curNode( do_QueryInterface(isupports ) );
|
||||
PRInt32 offset;
|
||||
res = nsEditor::GetNodeLocation(curNode, address_of(curParent), &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// some logic for putting list items into nested lists...
|
||||
if (nsHTMLEditUtils::IsList(curParent))
|
||||
{
|
||||
if (!curList || transitionList[i])
|
||||
{
|
||||
nsAutoString listTag;
|
||||
nsEditor::GetTagString(curParent,listTag);
|
||||
ToLowerCase(listTag);
|
||||
// create a new nested list of correct type
|
||||
res = SplitAsNeeded(&listTag, address_of(curParent), &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mHTMLEditor->CreateNode(listTag, curParent, offset, getter_AddRefs(curList));
|
||||
if (NS_FAILED(res)) return res;
|
||||
// curList is now the correct thing to put curNode in
|
||||
// remember our new block for postprocessing
|
||||
mNewBlock = curList;
|
||||
}
|
||||
// tuck the node into the end of the active list
|
||||
PRUint32 listLen;
|
||||
res = mHTMLEditor->GetLengthOfDOMNode(curList, listLen);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mHTMLEditor->MoveNode(curNode, curList, listLen);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
else // not a list item
|
||||
{
|
||||
if (IsBlockNode(curNode)) {
|
||||
RelativeChangeIndentation(curNode, +1);
|
||||
curQuote = nsnull;
|
||||
}
|
||||
else {
|
||||
if (!curQuote) // || transitionList[i])
|
||||
{
|
||||
nsAutoString quoteType; quoteType.Assign(NS_LITERAL_STRING("div"));
|
||||
res = SplitAsNeeded("eType, address_of(curParent), &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mHTMLEditor->CreateNode(quoteType, curParent, offset, getter_AddRefs(curQuote));
|
||||
if (NS_FAILED(res)) return res;
|
||||
RelativeChangeIndentation(curQuote, +1);
|
||||
// remember our new block for postprocessing
|
||||
mNewBlock = curQuote;
|
||||
// curQuote is now the correct thing to put curNode in
|
||||
}
|
||||
|
||||
// tuck the node into the end of the active blockquote
|
||||
PRUint32 quoteLen;
|
||||
res = mHTMLEditor->GetLengthOfDOMNode(curQuote, quoteLen);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mHTMLEditor->MoveNode(curNode, curQuote, quoteLen);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::WillHTMLIndent(nsISelection *aSelection, PRBool *aCancel, PRBool * aHandled)
|
||||
{
|
||||
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
nsresult res = WillInsert(aSelection, aCancel);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// initialize out param
|
||||
// we want to ignore result of WillInsert()
|
||||
*aCancel = PR_FALSE;
|
||||
*aHandled = PR_TRUE;
|
||||
|
||||
nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor);
|
||||
|
||||
// convert the selection ranges into "promoted" selection ranges:
|
||||
// this basically just expands the range to include the immediate
|
||||
// block parent, and then further expands to include any ancestors
|
||||
// whose children are all in the range
|
||||
|
||||
nsCOMPtr<nsISupportsArray> arrayOfRanges;
|
||||
res = GetPromotedRanges(aSelection, address_of(arrayOfRanges), kIndent);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// use these ranges to contruct a list of nodes to act on.
|
||||
nsCOMPtr<nsISupportsArray> arrayOfNodes;
|
||||
res = GetNodesForOperation(arrayOfRanges, address_of(arrayOfNodes), kIndent);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if nothing visible in list, make an empty block
|
||||
if (ListIsEmptyLine(arrayOfNodes))
|
||||
{
|
||||
|
@ -3097,7 +3319,9 @@ nsHTMLEditRules::WillOutdent(nsISelection *aSelection, PRBool *aCancel, PRBool *
|
|||
*aHandled = PR_TRUE;
|
||||
nsresult res = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> rememberedLeftBQ, rememberedRightBQ;
|
||||
|
||||
PRBool useCSS;
|
||||
mHTMLEditor->IsCSSEnabled(&useCSS);
|
||||
|
||||
// some scoping for selection resetting - we may need to tweak it
|
||||
{
|
||||
nsAutoSelectionReset selectionResetter(aSelection, mHTMLEditor);
|
||||
|
@ -3246,6 +3470,9 @@ nsHTMLEditRules::WillOutdent(nsISelection *aSelection, PRBool *aCancel, PRBool *
|
|||
res = mHTMLEditor->RemoveBlockContainer(curNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else if (useCSS) {
|
||||
RelativeChangeIndentation(curNode, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (curBlockQuote)
|
||||
|
@ -3599,11 +3826,11 @@ nsHTMLEditRules::WillAlign(nsISelection *aSelection,
|
|||
{
|
||||
// the node is a table element, an horiz rule, a paragraph, a div
|
||||
// or a section header; in HTML 4, it can directly carry the ALIGN
|
||||
// attribute and we don't need to make a div!
|
||||
// attribute and we don't need to make a div! If we are in CSS mode,
|
||||
// all the work is done in AlignBlock
|
||||
nsCOMPtr<nsIDOMElement> theElem = do_QueryInterface(theNode);
|
||||
res = mHTMLEditor->SetAttribute(theElem, NS_LITERAL_STRING("align"), *alignType);
|
||||
res = AlignBlock(theElem, alignType, PR_TRUE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
RemoveAlignmentInside(theNode);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -3660,9 +3887,9 @@ nsHTMLEditRules::WillAlign(nsISelection *aSelection,
|
|||
if (NS_FAILED(res)) return res;
|
||||
// remember our new block for postprocessing
|
||||
mNewBlock = theDiv;
|
||||
// set up the alignment on the div
|
||||
// set up the alignment on the div, using HTML or CSS
|
||||
nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(theDiv);
|
||||
res = mHTMLEditor->SetAttribute(divElem, NS_LITERAL_STRING("align"), *alignType);
|
||||
res = AlignBlock(divElem, alignType, PR_TRUE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
*aHandled = PR_TRUE;
|
||||
// put in a moz-br so that it won't get deleted
|
||||
|
@ -3686,6 +3913,8 @@ nsHTMLEditRules::WillAlign(nsISelection *aSelection,
|
|||
PRInt32 i;
|
||||
nsCOMPtr<nsIDOMNode> curParent;
|
||||
nsCOMPtr<nsIDOMNode> curDiv;
|
||||
PRBool useCSS;
|
||||
mHTMLEditor->IsCSSEnabled(&useCSS);
|
||||
for (i=0; i<(PRInt32)listCount; i++)
|
||||
{
|
||||
// here's where we actually figure out what to do
|
||||
|
@ -3697,16 +3926,15 @@ nsHTMLEditRules::WillAlign(nsISelection *aSelection,
|
|||
|
||||
// the node is a table element, an horiz rule, a paragraph, a div
|
||||
// or a section header; in HTML 4, it can directly carry the ALIGN
|
||||
// attribute and we don't need to nest it, just set the alignment
|
||||
// attribute and we don't need to nest it, just set the alignment.
|
||||
// In CSS, assign the corresponding CSS styles in AlignBlock
|
||||
if (nsHTMLEditUtils::SupportsAlignAttr(curNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(curNode);
|
||||
nsAutoString attr(NS_LITERAL_STRING("align"));
|
||||
res = mHTMLEditor->SetAttribute(divElem, attr, *alignType);
|
||||
nsCOMPtr<nsIDOMElement> curElem = do_QueryInterface(curNode);
|
||||
res = AlignBlock(curElem, alignType, PR_FALSE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// clear out curDiv so that we don't put nodes after this one into it
|
||||
curDiv = 0;
|
||||
RemoveAlignmentInside(curNode);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -3721,13 +3949,27 @@ nsHTMLEditRules::WillAlign(nsISelection *aSelection,
|
|||
// inside a list, forget any "current" div, and instead put divs inside
|
||||
// the appropriate block (td, li, etc)
|
||||
if ( nsHTMLEditUtils::IsListItem(curNode)
|
||||
|| (nsHTMLEditUtils::IsList(curNode) && nsHTMLEditUtils::IsList(curParent)))
|
||||
|| nsHTMLEditUtils::IsList(curNode))
|
||||
{
|
||||
res = AlignInnerBlocks(curNode, alignType);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (useCSS) {
|
||||
RemoveAlignment(curNode, *alignType, PR_TRUE);
|
||||
nsCOMPtr<nsIDOMElement> curElem = do_QueryInterface(curNode);
|
||||
nsAutoString attrName(NS_LITERAL_STRING("align"));
|
||||
PRInt32 count;
|
||||
mHTMLEditor->mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(curNode, nsnull,
|
||||
&attrName, alignType, &count);
|
||||
curDiv = 0;
|
||||
continue;
|
||||
}
|
||||
else if (nsHTMLEditUtils::IsList(curParent)) {
|
||||
// if we don't use CSS, add a contraint to list element : they have
|
||||
// to be inside another list, ie >= second level of nesting
|
||||
res = AlignInnerBlocks(curNode, alignType);
|
||||
if (NS_FAILED(res)) return res;
|
||||
curDiv = 0;
|
||||
continue;
|
||||
}
|
||||
// clear out curDiv so that we don't put nodes after this one into it
|
||||
curDiv = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// need to make a div to put things in if we haven't already,
|
||||
|
@ -3743,9 +3985,10 @@ nsHTMLEditRules::WillAlign(nsISelection *aSelection,
|
|||
mNewBlock = curDiv;
|
||||
// set up the alignment on the div
|
||||
nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(curDiv);
|
||||
nsAutoString attr(NS_LITERAL_STRING("align"));
|
||||
res = mHTMLEditor->SetAttribute(divElem, attr, *alignType);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = AlignBlock(divElem, alignType, PR_TRUE);
|
||||
// nsAutoString attr(NS_LITERAL_STRING("align"));
|
||||
// res = mHTMLEditor->SetAttribute(divElem, attr, *alignType);
|
||||
// if (NS_FAILED(res)) return res;
|
||||
// curDiv is now the correct thing to put curNode in
|
||||
}
|
||||
|
||||
|
@ -3806,10 +4049,14 @@ nsHTMLEditRules::AlignBlockContents(nsIDOMNode *aNode, const nsAReadableString *
|
|||
nsresult res;
|
||||
nsCOMPtr <nsIDOMNode> firstChild, lastChild, divNode;
|
||||
|
||||
PRBool useCSS;
|
||||
mHTMLEditor->IsCSSEnabled(&useCSS);
|
||||
|
||||
res = mHTMLEditor->GetFirstEditableChild(aNode, address_of(firstChild));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mHTMLEditor->GetLastEditableChild(aNode, address_of(lastChild));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsAutoString attr(NS_LITERAL_STRING("align"));
|
||||
if (!firstChild)
|
||||
{
|
||||
// this cell has no content, nothing to align
|
||||
|
@ -3819,8 +4066,14 @@ nsHTMLEditRules::AlignBlockContents(nsIDOMNode *aNode, const nsAReadableString *
|
|||
// the cell already has a div containing all of it's content: just
|
||||
// act on this div.
|
||||
nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(firstChild);
|
||||
nsAutoString attr(NS_LITERAL_STRING("align"));
|
||||
res = mHTMLEditor->SetAttribute(divElem, attr, *alignType);
|
||||
if (useCSS) {
|
||||
res = mHTMLEditor->RemoveAttribute(divElem, attr);
|
||||
mHTMLEditor->SetCSSEquivalentToHTMLStyle(divElem, attr, *alignType);
|
||||
}
|
||||
else {
|
||||
res = mHTMLEditor->SetAttribute(divElem, attr, *alignType);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else
|
||||
|
@ -3831,9 +4084,14 @@ nsHTMLEditRules::AlignBlockContents(nsIDOMNode *aNode, const nsAReadableString *
|
|||
if (NS_FAILED(res)) return res;
|
||||
// set up the alignment on the div
|
||||
nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(divNode);
|
||||
nsAutoString attr(NS_LITERAL_STRING("align"));
|
||||
res = mHTMLEditor->SetAttribute(divElem, attr, *alignType);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (useCSS) {
|
||||
res = mHTMLEditor->RemoveAttribute(divElem, attr);
|
||||
mHTMLEditor->SetCSSEquivalentToHTMLStyle(divElem, attr, *alignType);
|
||||
}
|
||||
else {
|
||||
res = mHTMLEditor->SetAttribute(divElem, attr, *alignType);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
// tuck the children into the end of the active div
|
||||
while (lastChild && (lastChild != divNode))
|
||||
{
|
||||
|
@ -4495,6 +4753,9 @@ nsHTMLEditRules::GetNodesForOperation(nsISupportsArray *inArrayOfRanges,
|
|||
nsCOMPtr<nsIDOMRange> opRange;
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
|
||||
PRBool useCSS;
|
||||
mHTMLEditor->IsCSSEnabled(&useCSS);
|
||||
|
||||
// bust up any inlines that cross our range endpoints,
|
||||
// but only if we are allowed to touch content.
|
||||
|
||||
|
@ -4550,8 +4811,7 @@ nsHTMLEditRules::GetNodesForOperation(nsISupportsArray *inArrayOfRanges,
|
|||
|
||||
// certain operations should not act on li's and td's, but rather inside
|
||||
// them. alter the list as needed
|
||||
if ( (inOperationType == kMakeBasicBlock) ||
|
||||
(inOperationType == kAlign) )
|
||||
if (inOperationType == kMakeBasicBlock)
|
||||
{
|
||||
PRUint32 listCount;
|
||||
(*outArrayOfNodes)->Count(&listCount);
|
||||
|
@ -4587,7 +4847,7 @@ nsHTMLEditRules::GetNodesForOperation(nsISupportsArray *inArrayOfRanges,
|
|||
}
|
||||
}
|
||||
// outdent should look inside of divs.
|
||||
if (inOperationType == kOutdent)
|
||||
if (inOperationType == kOutdent && !useCSS)
|
||||
{
|
||||
PRUint32 listCount;
|
||||
(*outArrayOfNodes)->Count(&listCount);
|
||||
|
@ -5559,6 +5819,7 @@ nsHTMLEditRules::MakeBlockquote(nsISupportsArray *arrayOfNodes)
|
|||
}
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
curNode->GetParentNode(getter_AddRefs(prevParent));
|
||||
}
|
||||
|
@ -6313,6 +6574,7 @@ nsHTMLEditRules::AdjustSelection(nsISelection *aSelection, nsIEditor::EDirection
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// we aren't in a textnode: are we adjacent to a break or an image?
|
||||
res = mHTMLEditor->GetPriorHTMLSibling(selNode, selOffset, address_of(nearNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
@ -7269,25 +7531,36 @@ nsHTMLEditRules::DidDeleteSelection(nsISelection *aSelection)
|
|||
// element (here we have to remove the container and keep its
|
||||
// children). We break on tables and don't look at their children.
|
||||
nsresult
|
||||
nsHTMLEditRules::RemoveAlignmentInside(nsIDOMNode * aNode)
|
||||
nsHTMLEditRules::RemoveAlignment(nsIDOMNode * aNode, nsAReadableString & aAlignType, PRBool aChildrenOnly)
|
||||
{
|
||||
if (!aNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (mHTMLEditor->IsTextNode(aNode) || nsHTMLEditUtils::IsTable(aNode)) return NS_OK;
|
||||
nsresult res = NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> child,tmp;
|
||||
aNode->GetFirstChild(getter_AddRefs(child));
|
||||
nsCOMPtr<nsIDOMNode> child = aNode,tmp;
|
||||
if (aChildrenOnly)
|
||||
{
|
||||
aNode->GetFirstChild(getter_AddRefs(child));
|
||||
}
|
||||
PRBool useCSS;
|
||||
mHTMLEditor->IsCSSEnabled(&useCSS);
|
||||
|
||||
while (child)
|
||||
{
|
||||
// get the next sibling right now because we could have to remove child
|
||||
child->GetNextSibling(getter_AddRefs(tmp));
|
||||
if (aChildrenOnly) {
|
||||
// get the next sibling right now because we could have to remove child
|
||||
child->GetNextSibling(getter_AddRefs(tmp));
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = nsnull;
|
||||
}
|
||||
PRBool isBlock;
|
||||
res = mHTMLEditor->NodeIsBlockStatic(child, &isBlock);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (isBlock)
|
||||
if (isBlock || nsHTMLEditUtils::IsHR(child))
|
||||
{
|
||||
// the current node is a block element
|
||||
nsCOMPtr<nsIDOMElement> curElem = do_QueryInterface(child);
|
||||
|
@ -7297,10 +7570,22 @@ nsHTMLEditRules::RemoveAlignmentInside(nsIDOMNode * aNode)
|
|||
res = mHTMLEditor->RemoveAttribute(curElem, NS_LITERAL_STRING("align"));
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
if (useCSS)
|
||||
{
|
||||
if (nsHTMLEditUtils::IsTable(child) || nsHTMLEditUtils::IsHR(child))
|
||||
{
|
||||
mHTMLEditor->SetCSSEquivalentToHTMLStyle(curElem, NS_LITERAL_STRING("align"), aAlignType);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsAutoString dummyCssValue;
|
||||
mHTMLEditor->mHTMLCSSUtils->RemoveCSSInlineStyle(child, nsIEditProperty::cssTextAlign, dummyCssValue);
|
||||
}
|
||||
}
|
||||
if (!nsHTMLEditUtils::IsTable(child))
|
||||
{
|
||||
// unless this is a table, look at children
|
||||
res = RemoveAlignmentInside(child);
|
||||
res = RemoveAlignment(child, aAlignType, PR_TRUE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
|
@ -7308,7 +7593,7 @@ nsHTMLEditRules::RemoveAlignmentInside(nsIDOMNode * aNode)
|
|||
{
|
||||
// this is a CENTER element and we have to remove it
|
||||
// first remove children's alignment
|
||||
res = RemoveAlignmentInside(child);
|
||||
res = RemoveAlignment(child, aAlignType, PR_TRUE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// we may have to insert BRs in first and last position of CENTER's children
|
||||
|
@ -7405,3 +7690,115 @@ nsHTMLEditRules::MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode)
|
|||
return res;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::AlignBlock(nsIDOMElement * aElement, const nsAReadableString * aAlignType, PRBool aContentsOnly)
|
||||
{
|
||||
if (!aElement) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
|
||||
PRBool isBlock = IsBlockNode(node);
|
||||
if (!isBlock && !nsHTMLEditUtils::IsHR(node)) {
|
||||
// we deal only with blocks; early way out
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RemoveAlignment(node, *aAlignType, aContentsOnly);
|
||||
nsAutoString attr(NS_LITERAL_STRING("align"));
|
||||
PRBool useCSS;
|
||||
nsresult res;
|
||||
mHTMLEditor->IsCSSEnabled(&useCSS);
|
||||
if (useCSS) {
|
||||
// let's use CSS alignment; we use margin-left and margin-right for tables
|
||||
// and text-align for other block-level elements
|
||||
res = mHTMLEditor->RemoveAttribute(aElement, attr);
|
||||
if (NS_FAILED(res)) return res;
|
||||
mHTMLEditor->SetCSSEquivalentToHTMLStyle(aElement, attr, *aAlignType);
|
||||
}
|
||||
else {
|
||||
// HTML case; this code is supposed to be called ONLY if the element
|
||||
// supports the align attribute but we'll never know...
|
||||
if (nsHTMLEditUtils::SupportsAlignAttr(node)) {
|
||||
res = mHTMLEditor->SetAttribute(aElement, attr, *aAlignType);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditRules::RelativeChangeIndentation(nsIDOMNode *aNode, PRInt8 aRelativeChange)
|
||||
{
|
||||
if ( !( (aRelativeChange==1) || (aRelativeChange==-1) ) )
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
nsAutoString value;
|
||||
nsresult res;
|
||||
mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(aNode, nsIEditProperty::cssMarginLeft, value);
|
||||
float f;
|
||||
nsIAtom * unit;
|
||||
mHTMLEditor->mHTMLCSSUtils->ParseLength(value, &f, &unit);
|
||||
if (0 == f) {
|
||||
NS_IF_RELEASE(unit);
|
||||
nsAutoString defaultLengthUnit;
|
||||
mHTMLEditor->mHTMLCSSUtils->GetDefaultLengthUnit(defaultLengthUnit);
|
||||
unit = NS_NewAtom(defaultLengthUnit);
|
||||
}
|
||||
nsAutoString unitString;
|
||||
unit->ToString(unitString);
|
||||
if (nsIEditProperty::cssInUnit == unit)
|
||||
f += NS_EDITOR_INDENT_INCREMENT_IN * aRelativeChange;
|
||||
else if (nsIEditProperty::cssCmUnit == unit)
|
||||
f += NS_EDITOR_INDENT_INCREMENT_CM * aRelativeChange;
|
||||
else if (nsIEditProperty::cssMmUnit == unit)
|
||||
f += NS_EDITOR_INDENT_INCREMENT_MM * aRelativeChange;
|
||||
else if (nsIEditProperty::cssPtUnit == unit)
|
||||
f += NS_EDITOR_INDENT_INCREMENT_PT * aRelativeChange;
|
||||
else if (nsIEditProperty::cssPcUnit == unit)
|
||||
f += NS_EDITOR_INDENT_INCREMENT_PC * aRelativeChange;
|
||||
else if (nsIEditProperty::cssEmUnit == unit)
|
||||
f += NS_EDITOR_INDENT_INCREMENT_EM * aRelativeChange;
|
||||
else if (nsIEditProperty::cssExUnit == unit)
|
||||
f += NS_EDITOR_INDENT_INCREMENT_EX * aRelativeChange;
|
||||
else if (nsIEditProperty::cssPxUnit == unit)
|
||||
f += NS_EDITOR_INDENT_INCREMENT_PX * aRelativeChange;
|
||||
else if (nsIEditProperty::cssPercentUnit == unit)
|
||||
f += NS_EDITOR_INDENT_INCREMENT_PERCENT * aRelativeChange;
|
||||
|
||||
NS_IF_RELEASE(unit);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
|
||||
if (element) {
|
||||
if (0 < f) {
|
||||
nsAutoString newValue;
|
||||
newValue.AppendFloat(f);
|
||||
newValue.Append(unitString);
|
||||
mHTMLEditor->mHTMLCSSUtils->SetCSSProperty(element, nsIEditProperty::cssMarginLeft, newValue);
|
||||
}
|
||||
else {
|
||||
mHTMLEditor->mHTMLCSSUtils->RemoveCSSProperty(element, nsIEditProperty::cssMarginLeft, value);
|
||||
if (nsHTMLEditUtils::IsDiv(aNode)) {
|
||||
// we deal with a DIV ; let's see if it is useless and if we can remove it
|
||||
nsCOMPtr<nsIDOMNamedNodeMap> attributeList;
|
||||
res = element->GetAttributes(getter_AddRefs(attributeList));
|
||||
if (NS_FAILED(res)) return res;
|
||||
PRUint32 count;
|
||||
attributeList->GetLength(&count);
|
||||
if (!count) {
|
||||
// the DIV has no attribute at all, let's remove it
|
||||
res = mHTMLEditor->RemoveContainer(element);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else if (1 == count) {
|
||||
nsCOMPtr<nsIDOMNode> styleAttributeNode;
|
||||
res = attributeList->GetNamedItem(NS_LITERAL_STRING("style"),
|
||||
getter_AddRefs(styleAttributeNode));
|
||||
if (!styleAttributeNode) {
|
||||
res = mHTMLEditor->RemoveContainer(element);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -138,6 +139,8 @@ protected:
|
|||
nsresult WillMakeList(nsISelection *aSelection, const nsAReadableString *aListType, PRBool aEntireList, const nsAReadableString *aBulletType, PRBool *aCancel, PRBool *aHandled, const nsAReadableString *aItemType=nsnull);
|
||||
nsresult WillRemoveList(nsISelection *aSelection, PRBool aOrderd, PRBool *aCancel, PRBool *aHandled);
|
||||
nsresult WillIndent(nsISelection *aSelection, PRBool *aCancel, PRBool *aHandled);
|
||||
nsresult WillCSSIndent(nsISelection *aSelection, PRBool *aCancel, PRBool *aHandled);
|
||||
nsresult WillHTMLIndent(nsISelection *aSelection, PRBool *aCancel, PRBool *aHandled);
|
||||
nsresult WillOutdent(nsISelection *aSelection, PRBool *aCancel, PRBool *aHandled);
|
||||
nsresult WillAlign(nsISelection *aSelection, const nsAReadableString *alignType, PRBool *aCancel, PRBool *aHandled);
|
||||
nsresult WillMakeDefListItem(nsISelection *aSelection, const nsAReadableString *aBlockType, PRBool aEntireList, PRBool *aCancel, PRBool *aHandled);
|
||||
|
@ -235,9 +238,11 @@ protected:
|
|||
PRBool IsVisBreak(nsIDOMNode *aNode);
|
||||
PRBool IsEmptyInline(nsIDOMNode *aNode);
|
||||
PRBool ListIsEmptyLine(nsISupportsArray *arrayOfNodes);
|
||||
nsresult RemoveAlignmentInside(nsIDOMNode * aNode);
|
||||
nsresult RemoveAlignment(nsIDOMNode * aNode, nsAReadableString & aAlignType, PRBool aChildrenOnly);
|
||||
nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode, PRBool aStarts);
|
||||
nsresult MakeSureElemStartsOrEndsOnCR(nsIDOMNode *aNode);
|
||||
nsresult AlignBlock(nsIDOMElement * aElement, const nsAReadableString * aAlignType, PRBool aContentsOnly);
|
||||
nsresult RelativeChangeIndentation(nsIDOMNode *aNode, PRInt8 aRelativeChange);
|
||||
|
||||
// data members
|
||||
protected:
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -65,6 +66,7 @@
|
|||
#include "nsISelectionPrivate.h"
|
||||
#include "nsIDOMHTMLAnchorElement.h"
|
||||
#include "nsISelectionController.h"
|
||||
#include "nsIDOMHTMLHtmlElement.h"
|
||||
|
||||
#include "TransactionFactory.h"
|
||||
|
||||
|
@ -164,6 +166,7 @@ nsHTMLEditor::nsHTMLEditor()
|
|||
, mIgnoreSpuriousDragEvent(PR_FALSE)
|
||||
, mTypeInState(nsnull)
|
||||
, mSelectedCellIndex(0)
|
||||
, mHTMLCSSUtils(nsnull)
|
||||
{
|
||||
// Done in nsEditor
|
||||
// NS_INIT_REFCNT();
|
||||
|
@ -272,6 +275,14 @@ NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc,
|
|||
result = nsPlaintextEditor::Init(aDoc, aPresShell, aRoot, aSelCon, aFlags);
|
||||
if (NS_FAILED(result)) { return result; }
|
||||
|
||||
// the HTML Editor is CSS-aware only in the case of Composer
|
||||
mCSSAware = PRBool(0 == aFlags);
|
||||
|
||||
// Init the HTML-CSS utils
|
||||
result = NS_NewHTMLCSSUtils(&mHTMLCSSUtils);
|
||||
if (NS_FAILED(result)) { return result; }
|
||||
mHTMLCSSUtils->Init(this);
|
||||
|
||||
// disable links
|
||||
nsCOMPtr<nsIPresContext> context;
|
||||
aPresShell->GetPresContext(getter_AddRefs(context));
|
||||
|
@ -586,19 +597,19 @@ nsHTMLEditor::NodeIsBlockStatic(nsIDOMNode *aNode, PRBool *aIsBlock)
|
|||
tagAtom==nsIEditProperty::noscript ||
|
||||
tagAtom==nsIEditProperty::form ||
|
||||
tagAtom==nsIEditProperty::hr ||
|
||||
tagAtom==nsIEditProperty::table ||
|
||||
tagAtom==nsIEditProperty::fieldset ||
|
||||
tagAtom==nsIEditProperty::address ||
|
||||
tagAtom==nsIEditProperty::body ||
|
||||
tagAtom==nsIEditProperty::tr ||
|
||||
tagAtom==nsIEditProperty::td ||
|
||||
tagAtom==nsIEditProperty::th ||
|
||||
tagAtom==nsIEditProperty::caption ||
|
||||
tagAtom==nsIEditProperty::col ||
|
||||
tagAtom==nsIEditProperty::colgroup ||
|
||||
tagAtom==nsIEditProperty::table ||
|
||||
tagAtom==nsIEditProperty::tbody ||
|
||||
tagAtom==nsIEditProperty::thead ||
|
||||
tagAtom==nsIEditProperty::tfoot ||
|
||||
tagAtom==nsIEditProperty::tr ||
|
||||
tagAtom==nsIEditProperty::td ||
|
||||
tagAtom==nsIEditProperty::th ||
|
||||
tagAtom==nsIEditProperty::col ||
|
||||
tagAtom==nsIEditProperty::colgroup ||
|
||||
tagAtom==nsIEditProperty::li ||
|
||||
tagAtom==nsIEditProperty::dt ||
|
||||
tagAtom==nsIEditProperty::dd ||
|
||||
|
@ -1166,9 +1177,14 @@ NS_IMETHODIMP nsHTMLEditor::HandleKeyPress(nsIDOMKeyEvent* aKeyEvent)
|
|||
}
|
||||
else if (keyCode == nsIDOMKeyEvent::DOM_VK_ESCAPE)
|
||||
{
|
||||
// pass escape keypresses through as empty strings: needed forime support
|
||||
nsString empty;
|
||||
return TypedText(empty, eTypedText);
|
||||
if (isShift) {
|
||||
return SelectParentOfSelection();
|
||||
}
|
||||
else {
|
||||
// pass escape keypresses through as empty strings: needed forime support
|
||||
nsString empty;
|
||||
return TypedText(empty, eTypedText);
|
||||
}
|
||||
}
|
||||
|
||||
// if we got here we either fell out of the tab case or have a normal character.
|
||||
|
@ -2103,8 +2119,163 @@ nsHTMLEditor::GetParagraphState(PRBool *aMixed, nsAWritableString &outFormat)
|
|||
return htmlRules->GetParagraphState(aMixed, outFormat);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::GetBackgroundColorState(PRBool *aMixed, nsAWritableString &aOutColor)
|
||||
{
|
||||
nsresult res;
|
||||
PRBool useCSS;
|
||||
IsCSSEnabled(&useCSS);
|
||||
if (useCSS) {
|
||||
// if we are in CSS mode, we have to check if the containing block defines
|
||||
// a background color
|
||||
res = GetCSSBackgroundColorState(aMixed, aOutColor, PR_TRUE);
|
||||
}
|
||||
else {
|
||||
// in HTML mode, we look only at page's background
|
||||
res = GetHTMLBackgroundColorState(aMixed, aOutColor);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::GetHighlightColorState(PRBool *aMixed, nsAWritableString &aOutColor)
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
PRBool useCSS;
|
||||
IsCSSEnabled(&useCSS);
|
||||
*aMixed = PR_FALSE;
|
||||
aOutColor.Assign(NS_LITERAL_STRING("transparent"));
|
||||
if (useCSS) {
|
||||
// in CSS mode, text background can be added by the Text Highlight button
|
||||
// we need to query the background of the selection without looking for
|
||||
// the block container of the ranges in the selection
|
||||
res = GetCSSBackgroundColorState(aMixed, aOutColor, PR_FALSE);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::GetHighlightColor(PRBool *aMixed, PRUnichar **_retval)
|
||||
{
|
||||
if (!aMixed || !_retval) return NS_ERROR_NULL_POINTER;
|
||||
nsAutoString outColorString(NS_LITERAL_STRING("transparent"));
|
||||
*aMixed = PR_FALSE;
|
||||
|
||||
nsresult err = NS_NOINTERFACE;
|
||||
err = GetHighlightColorState(aMixed, outColorString);
|
||||
*_retval = ToNewUnicode(outColorString);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::GetCSSBackgroundColorState(PRBool *aMixed, nsAWritableString &aOutColor, PRBool aBlockLevel)
|
||||
{
|
||||
if (!aMixed) return NS_ERROR_NULL_POINTER;
|
||||
*aMixed = PR_FALSE;
|
||||
// the default background color is transparent
|
||||
aOutColor.Assign(NS_LITERAL_STRING("transparent"));
|
||||
|
||||
// get selection
|
||||
nsCOMPtr<nsISelection>selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// get selection location
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
PRInt32 offset;
|
||||
res = GetStartNodeAndOffset(selection, address_of(parent), &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// is the selection collapsed?
|
||||
PRBool bCollapsed;
|
||||
res = selection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsIDOMNode> nodeToExamine;
|
||||
if (bCollapsed || IsTextNode(parent))
|
||||
{
|
||||
// we want to look at the parent and ancestors
|
||||
nodeToExamine = parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise we want to look at the first editable node after
|
||||
// {parent,offset} and it's ancestors for divs with alignment on them
|
||||
nodeToExamine = GetChildAt(parent, offset);
|
||||
//GetNextNode(parent, offset, PR_TRUE, address_of(nodeToExamine));
|
||||
}
|
||||
|
||||
if (!nodeToExamine) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// is the node to examine a block ?
|
||||
PRBool isBlock;
|
||||
res = NodeIsBlockStatic(nodeToExamine, &isBlock);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLHtmlElement> htmlElement;
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
|
||||
if (aBlockLevel) {
|
||||
// we are querying the block background (and not the text background), let's
|
||||
// climb to the block container
|
||||
nsCOMPtr<nsIDOMNode> blockParent = nodeToExamine;
|
||||
if (!isBlock) {
|
||||
blockParent = GetBlockNodeParent(nodeToExamine);
|
||||
}
|
||||
do {
|
||||
// retrieve the computed style of background-color for blockParent
|
||||
mHTMLCSSUtils->GetComputedProperty(blockParent, nsIEditProperty::cssBackgroundColor,
|
||||
aOutColor);
|
||||
tmp = blockParent;
|
||||
res = tmp->GetParentNode(getter_AddRefs(blockParent));
|
||||
htmlElement = do_QueryInterface(tmp);
|
||||
// look at parent if the queried color is transparent and if the node to
|
||||
// examine is not the root of the document
|
||||
} while ( aOutColor.Equals(NS_LITERAL_STRING("transparent")) && !htmlElement );
|
||||
if (htmlElement && aOutColor.Equals(NS_LITERAL_STRING("transparent"))) {
|
||||
// we have hit the root of the document and the color is still transparent !
|
||||
// Grumble... Let's look at the default background color because that's the
|
||||
// color we are looking for
|
||||
mHTMLCSSUtils->GetDefaultBackgroundColor(aOutColor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no, we are querying the text background for the Text Highlight button
|
||||
if (IsTextNode(nodeToExamine)) {
|
||||
// if the node of interest is a text node, let's climb a level
|
||||
res = nodeToExamine->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nodeToExamine = parent;
|
||||
}
|
||||
do {
|
||||
// is the node to examine a block ?
|
||||
res = NodeIsBlockStatic(nodeToExamine, &isBlock);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (isBlock) {
|
||||
// yes it is a block; in that case, the text background color is transparent
|
||||
aOutColor.Assign(NS_LITERAL_STRING("transparent"));
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// no, it's not; let's retrieve the computed style of background-color for the
|
||||
// node to examine
|
||||
mHTMLCSSUtils->GetComputedProperty(nodeToExamine, nsIEditProperty::cssBackgroundColor,
|
||||
aOutColor);
|
||||
if (!aOutColor.Equals(NS_LITERAL_STRING("transparent"))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
res = nodeToExamine->GetParentNode(getter_AddRefs(tmp));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nodeToExamine = tmp;
|
||||
htmlElement = do_QueryInterface(tmp);
|
||||
} while ( aOutColor.Equals(NS_LITERAL_STRING("transparent")) && !htmlElement );
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::GetHTMLBackgroundColorState(PRBool *aMixed, nsAWritableString &aOutColor)
|
||||
{
|
||||
//TODO: We don't handle "mixed" correctly!
|
||||
if (!aMixed) return NS_ERROR_NULL_POINTER;
|
||||
|
@ -3032,8 +3203,8 @@ nsHTMLEditor::InsertLinkAroundSelection(nsIDOMElement* aAnchorElement)
|
|||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::SetBackgroundColor(const nsAReadableString& aColor)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::SetHTMLBackgroundColor(const nsAReadableString& aColor)
|
||||
{
|
||||
NS_PRECONDITION(mDocWeak, "Missing Editor DOM Document");
|
||||
|
||||
|
@ -4831,3 +5002,415 @@ nsHTMLEditor::IsEmptyNode( nsIDOMNode *aNode,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// add to aElement the CSS inline styles corresponding to the HTML attribute
|
||||
// aAttribute with its value aValue
|
||||
nsresult
|
||||
nsHTMLEditor::SetCSSEquivalentToHTMLStyle(nsIDOMElement * aElement,
|
||||
const nsAReadableString & aAttribute,
|
||||
const nsAReadableString & aValue)
|
||||
{
|
||||
PRBool useCSS;
|
||||
nsresult res = NS_OK;
|
||||
IsCSSEnabled(&useCSS);
|
||||
if (useCSS && mHTMLCSSUtils) {
|
||||
PRInt32 count;
|
||||
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(aElement, nsnull, &aAttribute, &aValue, &count);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!count) {
|
||||
// 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.Equals(NS_LITERAL_STRING("style"))) {
|
||||
// if it is the style attribute, just add the new value to the existing style
|
||||
// attribute's value
|
||||
nsAutoString existingValue;
|
||||
PRBool wasSet = PR_FALSE;
|
||||
res = GetAttributeValue(aElement, NS_LITERAL_STRING("style"), existingValue, &wasSet);
|
||||
if (NS_FAILED(res)) return res;
|
||||
existingValue.Append(NS_LITERAL_STRING(" "));
|
||||
existingValue.Append(aValue);
|
||||
res = SetAttribute(aElement, aAttribute, existingValue);
|
||||
}
|
||||
else {
|
||||
// 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
|
||||
res = SetAttribute(aElement, aAttribute, aValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// we are not in an HTML+CSS editor; let's set the attribute the HTML way
|
||||
res = SetAttribute(aElement, aAttribute, aValue);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::SetCSSEnabled(PRBool aIsCSSPrefChecked)
|
||||
{
|
||||
nsresult err = NS_ERROR_NOT_INITIALIZED;
|
||||
if (mHTMLCSSUtils)
|
||||
{
|
||||
err = mHTMLCSSUtils->SetCSSEnabled(aIsCSSPrefChecked);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// Set the block background color
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::SetCSSBackgroundColor(const nsAReadableString& aColor)
|
||||
{
|
||||
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
ForceCompositionEnd();
|
||||
|
||||
nsresult res;
|
||||
nsCOMPtr<nsISelection>selection;
|
||||
res = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!selection) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));
|
||||
|
||||
PRBool isCollapsed;
|
||||
selection->GetIsCollapsed(&isCollapsed);
|
||||
|
||||
nsAutoEditBatch batchIt(this);
|
||||
nsAutoRules beginRulesSniffing(this, kOpInsertElement, nsIEditor::eNext);
|
||||
nsAutoSelectionReset selectionResetter(selection, this);
|
||||
nsAutoTxnsConserveSelection dontSpazMySelection(this);
|
||||
|
||||
PRBool cancel, handled;
|
||||
nsTextRulesInfo ruleInfo(nsTextEditRules::kSetTextProperty);
|
||||
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!cancel && !handled)
|
||||
{
|
||||
// get selection range enumerator
|
||||
nsCOMPtr<nsIEnumerator> enumerator;
|
||||
res = selPriv->GetEnumerator(getter_AddRefs(enumerator));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!enumerator) return NS_ERROR_FAILURE;
|
||||
|
||||
// loop thru the ranges in the selection
|
||||
enumerator->First();
|
||||
nsCOMPtr<nsISupports> currentItem;
|
||||
nsAutoString bgcolor; bgcolor.AssignWithConversion("bgcolor");
|
||||
nsCOMPtr<nsIDOMNode> cachedBlockParent = nsnull;
|
||||
while ((NS_ENUMERATOR_FALSE == enumerator->IsDone()))
|
||||
{
|
||||
res = enumerator->CurrentItem(getter_AddRefs(currentItem));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!currentItem) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
|
||||
// check for easy case: both range endpoints in same text node
|
||||
nsCOMPtr<nsIDOMNode> startNode, endNode;
|
||||
PRInt32 startOffset, endOffset;
|
||||
res = range->GetStartContainer(getter_AddRefs(startNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = range->GetEndContainer(getter_AddRefs(endNode));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = range->GetStartOffset(&startOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = range->GetEndOffset(&endOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if ((startNode == endNode) && IsTextNode(startNode))
|
||||
{
|
||||
// let's find the block container of the text node
|
||||
nsCOMPtr<nsIDOMNode> blockParent;
|
||||
blockParent = GetBlockNodeParent(startNode);
|
||||
// and apply the background color to that block container
|
||||
if (cachedBlockParent != blockParent)
|
||||
{
|
||||
cachedBlockParent = blockParent;
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent);
|
||||
PRInt32 count;
|
||||
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nsnull, &bgcolor, &aColor, &count);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
else if ((startNode == endNode) && nsTextEditUtils::IsBody(startNode) && !startOffset && !endOffset )
|
||||
{
|
||||
// we have no block in the document, let's apply the background to the body
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(startNode);
|
||||
PRInt32 count;
|
||||
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nsnull, &bgcolor, &aColor, &count);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
else if ((startNode == endNode) && (((endOffset-startOffset) == 1) || (!startOffset && !endOffset)))
|
||||
{
|
||||
// a unique node is selected, let's also apply the background color
|
||||
// to the containing block, possibly the node itself
|
||||
nsCOMPtr<nsIDOMNode> selectedNode = GetChildAt(startNode, startOffset);
|
||||
PRBool isBlock =PR_FALSE;
|
||||
res = NodeIsBlockStatic(selectedNode, &isBlock);
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsIDOMNode> blockParent = selectedNode;
|
||||
if (!isBlock) {
|
||||
blockParent = GetBlockNodeParent(selectedNode);
|
||||
}
|
||||
if (cachedBlockParent != blockParent)
|
||||
{
|
||||
cachedBlockParent = blockParent;
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent);
|
||||
PRInt32 count;
|
||||
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nsnull, &bgcolor, &aColor, &count);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// not the easy case. range not contained in single text node.
|
||||
// there are up to three phases here. There are all the nodes
|
||||
// reported by the subtree iterator to be processed. And there
|
||||
// are potentially a starting textnode and an ending textnode
|
||||
// which are only partially contained by the range.
|
||||
|
||||
// lets handle the nodes reported by the iterator. These nodes
|
||||
// are entirely contained in the selection range. We build up
|
||||
// a list of them (since doing operations on the document during
|
||||
// iteration would perturb the iterator).
|
||||
|
||||
nsCOMPtr<nsIContentIterator> iter;
|
||||
res = nsComponentManager::CreateInstance(kSubtreeIteratorCID, nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(iter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!iter) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISupportsArray> arrayOfNodes;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
|
||||
// make a array
|
||||
res = NS_NewISupportsArray(getter_AddRefs(arrayOfNodes));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// iterate range and build up array
|
||||
res = iter->Init(range);
|
||||
// init returns an error if no nodes in range.
|
||||
// this can easily happen with the subtree
|
||||
// iterator if the selection doesn't contain
|
||||
// any *whole* nodes.
|
||||
if (NS_SUCCEEDED(res))
|
||||
{
|
||||
while (NS_ENUMERATOR_FALSE == iter->IsDone())
|
||||
{
|
||||
res = iter->CurrentNode(getter_AddRefs(content));
|
||||
if (NS_FAILED(res)) return res;
|
||||
node = do_QueryInterface(content);
|
||||
if (!node) return NS_ERROR_FAILURE;
|
||||
if (IsEditable(node))
|
||||
{
|
||||
isupports = do_QueryInterface(node);
|
||||
arrayOfNodes->AppendElement(isupports);
|
||||
}
|
||||
res = iter->Next();
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
// first check the start parent of the range to see if it needs to
|
||||
// be seperately handled (it does if it's a text node, due to how the
|
||||
// subtree iterator works - it will not have reported it).
|
||||
if (IsTextNode(startNode) && IsEditable(startNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> blockParent;
|
||||
blockParent = GetBlockNodeParent(startNode);
|
||||
if (cachedBlockParent != blockParent)
|
||||
{
|
||||
cachedBlockParent = blockParent;
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent);
|
||||
PRInt32 count;
|
||||
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nsnull, &bgcolor, &aColor, &count);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
|
||||
// then loop through the list, set the property on each node
|
||||
PRUint32 listCount;
|
||||
PRUint32 j;
|
||||
arrayOfNodes->Count(&listCount);
|
||||
for (j = 0; j < listCount; j++)
|
||||
{
|
||||
isupports = dont_AddRef(arrayOfNodes->ElementAt(0));
|
||||
node = do_QueryInterface(isupports);
|
||||
// do we have a block here ?
|
||||
PRBool isBlock =PR_FALSE;
|
||||
res = NodeIsBlockStatic(node, &isBlock);
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsIDOMNode> blockParent = node;
|
||||
if (!isBlock) {
|
||||
// no we don't, let's find the block ancestor
|
||||
blockParent = GetBlockNodeParent(node);
|
||||
}
|
||||
if (cachedBlockParent != blockParent)
|
||||
{
|
||||
cachedBlockParent = blockParent;
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent);
|
||||
PRInt32 count;
|
||||
// and set the property on it
|
||||
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nsnull, &bgcolor, &aColor, &count);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
arrayOfNodes->RemoveElementAt(0);
|
||||
}
|
||||
|
||||
// last check the end parent of the range to see if it needs to
|
||||
// be seperately handled (it does if it's a text node, due to how the
|
||||
// subtree iterator works - it will not have reported it).
|
||||
if (IsTextNode(endNode) && IsEditable(endNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> blockParent;
|
||||
blockParent = GetBlockNodeParent(endNode);
|
||||
if (cachedBlockParent != blockParent)
|
||||
{
|
||||
cachedBlockParent = blockParent;
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent);
|
||||
PRInt32 count;
|
||||
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nsnull, &bgcolor, &aColor, &count);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->Next();
|
||||
}
|
||||
}
|
||||
if (!cancel)
|
||||
{
|
||||
// post-process
|
||||
res = mRules->DidDoAction(selection, &ruleInfo, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::SetBackgroundColor(const nsAReadableString& aColor)
|
||||
{
|
||||
nsresult res;
|
||||
PRBool useCSS;
|
||||
IsCSSEnabled(&useCSS);
|
||||
if (useCSS) {
|
||||
// if we are in CSS mode, we have to apply the background color to the
|
||||
// containing block (or the body if we have no block-level element in
|
||||
// the document)
|
||||
res = SetCSSBackgroundColor(aColor);
|
||||
}
|
||||
else {
|
||||
// but in HTML mode, we can only set the document's background color
|
||||
res = SetHTMLBackgroundColor(aColor);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// NodesSameType: do these nodes have the same tag?
|
||||
//
|
||||
PRBool
|
||||
nsHTMLEditor::NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2)
|
||||
{
|
||||
if (!aNode1 || !aNode2)
|
||||
{
|
||||
NS_NOTREACHED("null node passed to nsEditor::NodesSameType()");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool useCSS;
|
||||
IsCSSEnabled(&useCSS);
|
||||
|
||||
nsCOMPtr<nsIAtom> atom1 = GetTag(aNode1);
|
||||
nsCOMPtr<nsIAtom> atom2 = GetTag(aNode2);
|
||||
|
||||
if (atom1.get() == atom2.get()) {
|
||||
if (useCSS && NodeIsType(aNode1, NS_LITERAL_STRING("span"))) {
|
||||
if (mHTMLCSSUtils->ElementsSameStyle(aNode1, aNode2)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLEditor::SelectParentOfSelection()
|
||||
{
|
||||
// get selection
|
||||
nsCOMPtr<nsISelection>selection;
|
||||
nsresult res = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));
|
||||
if (!selPriv)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRBool bCollapsed;
|
||||
res = selection->GetIsCollapsed(&bCollapsed);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (bCollapsed) {
|
||||
// get selection location
|
||||
nsCOMPtr<nsIDOMNode> node, parent;
|
||||
PRInt32 offset;
|
||||
res = GetStartNodeAndOffset(selection, address_of(node), &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
res = node->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res) || !parent) return res;
|
||||
nsCOMPtr<nsIDOMElement> resultElement = do_QueryInterface(parent);
|
||||
if (!resultElement) return NS_OK;
|
||||
res = SelectElement(resultElement);
|
||||
return res;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIEnumerator> enumerator;
|
||||
res = selPriv->GetEnumerator(getter_AddRefs(enumerator));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!enumerator) return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsISupportsArray> arrayOfNodes;
|
||||
// make a array
|
||||
res = NS_NewISupportsArray(getter_AddRefs(arrayOfNodes));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
|
||||
for (enumerator->First(); NS_OK!=enumerator->IsDone(); enumerator->Next())
|
||||
{
|
||||
nsCOMPtr<nsISupports> currentItem;
|
||||
res = enumerator->CurrentItem(getter_AddRefs(currentItem));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!currentItem) return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
||||
nsCOMPtr<nsIDOMNode> commonParent;
|
||||
range->GetCommonAncestorContainer(getter_AddRefs(commonParent));
|
||||
|
||||
isupports = do_QueryInterface(commonParent);
|
||||
res = arrayOfNodes->AppendElement(isupports);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
PRUint32 listCount;
|
||||
arrayOfNodes->Count(&listCount);
|
||||
// res = ClearSelection();
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
PRUint32 j;
|
||||
|
||||
for (j = 0; j < listCount; j++)
|
||||
{
|
||||
isupports = dont_AddRef(arrayOfNodes->ElementAt(j));
|
||||
node = do_QueryInterface(isupports);
|
||||
element = do_QueryInterface(node);
|
||||
if (IsElementInBody(element))
|
||||
{
|
||||
res = AppendNodeToSelectionAsRange(node);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -59,7 +60,8 @@
|
|||
#include "nsEditRules.h"
|
||||
|
||||
#include "nsIEditProperty.h"
|
||||
|
||||
#include "nsHTMLCSSUtils.h"
|
||||
|
||||
class nsIDOMKeyEvent;
|
||||
class nsITransferable;
|
||||
class nsIDOMEventReceiver;
|
||||
|
@ -116,9 +118,14 @@ public:
|
|||
NS_IMETHODIMP CollapseSelectionToStart();
|
||||
|
||||
/* ------------ nsIHTMLEditor methods -------------- */
|
||||
|
||||
NS_IMETHOD SetCSSInlineProperty(nsIAtom *aProperty,
|
||||
const nsAReadableString & aAttribute,
|
||||
const nsAReadableString & aValue);
|
||||
|
||||
NS_IMETHOD SetInlineProperty(nsIAtom *aProperty,
|
||||
const nsAReadableString & aAttribute,
|
||||
const nsAReadableString & aValue);
|
||||
const nsAReadableString & aAttribute,
|
||||
const nsAReadableString & aValue);
|
||||
|
||||
NS_IMETHOD GetInlineProperty(nsIAtom *aProperty,
|
||||
const nsAReadableString & aAttribute,
|
||||
|
@ -157,7 +164,11 @@ public:
|
|||
NS_IMETHOD GetParagraphState(PRBool *aMixed, nsAWritableString &outFormat);
|
||||
NS_IMETHOD GetFontFaceState(PRBool *aMixed, nsAWritableString &outFace);
|
||||
NS_IMETHOD GetFontColorState(PRBool *aMixed, nsAWritableString &outColor);
|
||||
NS_IMETHOD GetCSSBackgroundColorState(PRBool *aMixed, nsAWritableString &aOutColor, PRBool aBlockLevel);
|
||||
NS_IMETHOD GetHTMLBackgroundColorState(PRBool *aMixed, nsAWritableString &outColor);
|
||||
NS_IMETHOD GetBackgroundColorState(PRBool *aMixed, nsAWritableString &outColor);
|
||||
NS_IMETHOD GetHighlightColorState(PRBool *aMixed, nsAWritableString &outColor);
|
||||
NS_IMETHOD GetHighlightColor(PRBool *mixed, PRUnichar **_retval);
|
||||
NS_IMETHOD GetListState(PRBool *aMixed, PRBool *aOL, PRBool *aUL, PRBool *aDL);
|
||||
NS_IMETHOD GetListItemState(PRBool *aMixed, PRBool *aLI, PRBool *aDT, PRBool *aDD);
|
||||
NS_IMETHOD GetAlignment(PRBool *aMixed, nsIHTMLEditor::EAlignment *aAlign);
|
||||
|
@ -178,6 +189,8 @@ public:
|
|||
|
||||
NS_IMETHOD GetLinkedObjects(nsISupportsArray** aNodeList);
|
||||
|
||||
NS_IMETHOD SetCSSEnabled(PRBool aIsCSSPrefChecked);
|
||||
|
||||
/* ------------ nsIEditorIMESupport overrides -------------- */
|
||||
|
||||
NS_IMETHOD SetCompositionString(const nsAReadableString& aCompositionString, nsIPrivateTextRangeList* aTextRangeList,nsTextEventReply* aReply);
|
||||
|
@ -265,6 +278,8 @@ public:
|
|||
/* miscellaneous */
|
||||
// This sets background on the appropriate container element (table, cell,)
|
||||
// or calls into nsTextEditor to set the page background
|
||||
NS_IMETHOD SetCSSBackgroundColor(const nsAReadableString& aColor);
|
||||
NS_IMETHOD SetHTMLBackgroundColor(const nsAReadableString& aColor);
|
||||
NS_IMETHOD SetBackgroundColor(const nsAReadableString& aColor);
|
||||
NS_IMETHOD SetBodyAttribute(const nsAReadableString& aAttr, const nsAReadableString& aValue);
|
||||
// aTitle may be null or empty string to remove child contents of <title>
|
||||
|
@ -364,9 +379,16 @@ public:
|
|||
/** make the given selection span the entire document */
|
||||
NS_IMETHOD SelectEntireDocument(nsISelection *aSelection);
|
||||
|
||||
NS_IMETHOD IsCSSEnabled(PRBool * aIsSet);
|
||||
NS_IMETHOD SetCSSEquivalentToHTMLStyle(nsIDOMElement * aElement,
|
||||
const nsAReadableString & aAttribute,
|
||||
const nsAReadableString & aValue);
|
||||
|
||||
/** join together any afjacent editable text nodes in the range */
|
||||
NS_IMETHOD CollapseAdjacentTextNodes(nsIDOMRange *aInRange);
|
||||
|
||||
virtual PRBool NodesSameType(nsIDOMNode *aNode1, nsIDOMNode *aNode2);
|
||||
|
||||
/* ------------ nsICSSLoaderObserver -------------- */
|
||||
NS_IMETHOD StyleSheetLoaded(nsICSSStyleSheet*aSheet, PRBool aNotify);
|
||||
|
||||
|
@ -655,7 +677,7 @@ protected:
|
|||
const nsAReadableString *aAttribute,
|
||||
PRBool aChildrenOnly = PR_FALSE);
|
||||
nsresult RemoveInlinePropertyImpl(nsIAtom *aProperty, const nsAReadableString *aAttribute);
|
||||
|
||||
|
||||
PRBool NodeIsProperty(nsIDOMNode *aNode);
|
||||
PRBool HasAttr(nsIDOMNode *aNode, const nsAReadableString *aAttribute);
|
||||
PRBool HasAttrVal(nsIDOMNode *aNode, const nsAReadableString *aAttribute, const nsAReadableString *aValue);
|
||||
|
@ -696,6 +718,8 @@ protected:
|
|||
PRBool *aAll,
|
||||
nsAWritableString *outValue);
|
||||
|
||||
nsresult SelectParentOfSelection();
|
||||
|
||||
// Data members
|
||||
protected:
|
||||
|
||||
|
@ -721,6 +745,8 @@ protected:
|
|||
|
||||
nsCOMPtr<nsIRangeUtils> mRangeHelper;
|
||||
|
||||
PRBool mCSSAware;
|
||||
nsHTMLCSSUtils *mHTMLCSSUtils;
|
||||
public:
|
||||
|
||||
// friends
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -66,11 +67,9 @@
|
|||
#include "nsICSSLoader.h"
|
||||
#include "nsICSSStyleSheet.h"
|
||||
#include "nsIHTMLContentContainer.h"
|
||||
#include "nsIStyleSet.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
#include "nsIDocumentStateListener.h"
|
||||
|
||||
#include "nsIStyleContext.h"
|
||||
#include "TypeInState.h"
|
||||
|
||||
#include "nsIEnumerator.h"
|
||||
|
@ -99,6 +98,7 @@
|
|||
#include "nsInternetCiter.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "InsertTextTxn.h"
|
||||
#include "ChangeCSSInlineStyleTxn.h"
|
||||
|
||||
// Transactionas
|
||||
#include "PlaceholderTxn.h"
|
||||
|
@ -119,6 +119,21 @@ static PRBool gNoisy = PR_FALSE;
|
|||
static const PRBool gNoisy = PR_FALSE;
|
||||
#endif
|
||||
|
||||
// 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,
|
||||
const nsAReadableString & aAttribute,
|
||||
const nsAReadableString & aValue)
|
||||
{
|
||||
nsresult res = NS_OK;
|
||||
PRBool useCSS;
|
||||
|
||||
IsCSSEnabled(&useCSS);
|
||||
if (useCSS) {
|
||||
res = SetInlineProperty(aProperty, aAttribute, aValue);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty,
|
||||
const nsAReadableString & aAttribute,
|
||||
|
@ -305,11 +320,17 @@ nsHTMLEditor::SetInlinePropertyOnTextNode( nsIDOMCharacterData *aTextNode,
|
|||
const nsAReadableString *aValue)
|
||||
{
|
||||
if (!aTextNode) return NS_ERROR_NULL_POINTER;
|
||||
nsresult res = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
res = aTextNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsAutoString tagString;
|
||||
aProperty->ToString(tagString);
|
||||
if (!CanContainTag(parent, tagString)) return NS_OK;
|
||||
|
||||
// dont need to do anything if no characters actually selected
|
||||
if (aStartOffset == aEndOffset) return NS_OK;
|
||||
|
||||
nsresult res = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> tmp, node = do_QueryInterface(aTextNode);
|
||||
|
||||
// dont need to do anything if property already set on node
|
||||
|
@ -378,6 +399,38 @@ nsHTMLEditor::SetInlinePropertyOnNode( nsIDOMNode *aNode,
|
|||
aProperty->ToString(tag);
|
||||
ToLowerCase(tag);
|
||||
|
||||
PRBool useCSS;
|
||||
IsCSSEnabled(&useCSS);
|
||||
|
||||
if (useCSS) {
|
||||
// we are in CSS mode
|
||||
if (mHTMLCSSUtils->IsCSSEditableProperty(aNode, aProperty, aAttribute)) {
|
||||
// the HTML style defined by aProperty/aAttribute has a CSS equivalence
|
||||
// in this implementation for the node aNode
|
||||
nsCOMPtr<nsIDOMNode> tmp = aNode;
|
||||
if (IsTextNode(tmp)) {
|
||||
// we are working on a text node and need to create a span container
|
||||
// that will carry the styles
|
||||
InsertContainerAbove( aNode,
|
||||
address_of(tmp),
|
||||
NS_LITERAL_STRING("span"),
|
||||
nsnull,
|
||||
nsnull);
|
||||
}
|
||||
nsCOMPtr<nsIDOMElement>element;
|
||||
element = do_QueryInterface(tmp);
|
||||
// first we have to remove occurences of the same style hint in the
|
||||
// children of the aNode
|
||||
res = RemoveStyleInside(tmp, aProperty, aAttribute, PR_TRUE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
PRInt32 count;
|
||||
// then we add the css styles corresponding to the HTML style request
|
||||
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, aProperty, aAttribute, aValue, &count);
|
||||
if (NS_FAILED(res)) return res;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
// dont need to do anything if property already set on node
|
||||
PRBool bHasProp;
|
||||
nsCOMPtr<nsIDOMNode> styleNode;
|
||||
|
@ -497,7 +550,7 @@ nsresult nsHTMLEditor::SplitStyleAboveRange(nsIDOMRange *inRange,
|
|||
// split any matching style nodes above the start of range
|
||||
res = SplitStyleAbovePoint(address_of(startNode), &startOffset, aProperty, aAttribute);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
|
||||
if (sameNode && (startNode != origStartNode))
|
||||
{
|
||||
// our startNode got split. This changes the offset of the end of our range.
|
||||
|
@ -528,12 +581,27 @@ nsresult nsHTMLEditor::SplitStyleAbovePoint(nsCOMPtr<nsIDOMNode> *aNode,
|
|||
// split any matching style nodes above the node/offset
|
||||
nsCOMPtr<nsIDOMNode> parent, tmp = *aNode;
|
||||
PRInt32 offset;
|
||||
|
||||
|
||||
PRBool useCSS;
|
||||
IsCSSEnabled(&useCSS);
|
||||
|
||||
PRBool isSet;
|
||||
while (tmp && !IsBlockNode(tmp))
|
||||
{
|
||||
isSet = PR_FALSE;
|
||||
if (useCSS && mHTMLCSSUtils->IsCSSEditableProperty(tmp, aProperty, aAttribute)) {
|
||||
// the HTML style defined by aProperty/aAttribute has a CSS equivalence
|
||||
// in this implementation for the node tmp; let's check if it carries those css styles
|
||||
nsAutoString firstValue;
|
||||
mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(tmp, aProperty, aAttribute,
|
||||
isSet, firstValue,
|
||||
SPECIFIED_STYLE_TYPE);
|
||||
}
|
||||
if ( (aProperty && NodeIsType(tmp, aProperty)) || // node is the correct inline prop
|
||||
(aProperty == nsIEditProperty::href && nsHTMLEditUtils::IsLink(tmp)) || // node is href - test if really <a href=...
|
||||
(!aProperty && NodeIsProperty(tmp)) ) // or node is any prop, and we asked to split them all
|
||||
(aProperty == nsIEditProperty::href && nsHTMLEditUtils::IsLink(tmp)) ||
|
||||
// node is href - test if really <a href=...
|
||||
(!aProperty && NodeIsProperty(tmp)) || // or node is any prop, and we asked to split them all
|
||||
isSet) // or the style is specified in the style attribute
|
||||
{
|
||||
// found a style node we need to split
|
||||
SplitNodeDeep(tmp, *aNode, *aOffset, &offset, PR_FALSE, outLeftNode, outRightNode);
|
||||
|
@ -610,7 +678,44 @@ nsresult nsHTMLEditor::RemoveStyleInside(nsIDOMNode *aNode,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
PRBool useCSS;
|
||||
IsCSSEnabled(&useCSS);
|
||||
|
||||
if (!aChildrenOnly
|
||||
&& useCSS && mHTMLCSSUtils->IsCSSEditableProperty(aNode, aProperty, aAttribute)) {
|
||||
// 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 css styles
|
||||
nsAutoString propertyValue;
|
||||
PRBool isSet;
|
||||
mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(aNode, aProperty, aAttribute,
|
||||
isSet, propertyValue,
|
||||
SPECIFIED_STYLE_TYPE);
|
||||
if (isSet) {
|
||||
// yes, tmp has the corresponding css declarations in its style attribute
|
||||
// let's remove them
|
||||
mHTMLCSSUtils->RemoveCSSEquivalentToHTMLStyle(aNode,
|
||||
aProperty,
|
||||
aAttribute,
|
||||
&propertyValue);
|
||||
// remove the node if it is a span, if its style attribute is empty or absent,
|
||||
// and if it does not have a class nor an id
|
||||
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(aNode);
|
||||
nsAutoString styleVal;
|
||||
PRBool isStyleSet;
|
||||
res = GetAttributeValue(elem, NS_LITERAL_STRING("style"), styleVal, &isStyleSet);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (NodeIsType(aNode, nsIEditProperty::span) && (!isStyleSet || (0 == styleVal.Length()))) {
|
||||
PRBool hasClassOrId ;
|
||||
res = mHTMLCSSUtils->HasClassOrID(elem, hasClassOrId);
|
||||
if (!hasClassOrId) {
|
||||
res = RemoveContainer(aNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( aProperty == nsIEditProperty::font && // or node is big or small and we are setting font size
|
||||
(NodeIsType(aNode, nsIEditProperty::big) || NodeIsType(aNode, nsIEditProperty::small)) &&
|
||||
!Compare(*aAttribute,NS_LITERAL_STRING("size"),nsCaseInsensitiveStringComparator()))
|
||||
|
@ -869,6 +974,10 @@ nsHTMLEditor::GetInlinePropertyBase(nsIAtom *aProperty,
|
|||
*aAll=PR_TRUE;
|
||||
*aFirst=PR_FALSE;
|
||||
PRBool first=PR_TRUE;
|
||||
|
||||
PRBool useCSS;
|
||||
IsCSSEnabled(&useCSS);
|
||||
|
||||
nsCOMPtr<nsISelection>selection;
|
||||
result = GetSelection(getter_AddRefs(selection));
|
||||
if (NS_FAILED(result)) return result;
|
||||
|
@ -916,11 +1025,13 @@ nsHTMLEditor::GetInlinePropertyBase(nsIAtom *aProperty,
|
|||
*aFirst = *aAny = *aAll = theSetting;
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
IsTextPropertySetByContent(collapsedNode, aProperty, aAttribute, aValue,
|
||||
isSet, getter_AddRefs(resultNode), outValue);
|
||||
*aFirst = *aAny = *aAll = isSet;
|
||||
return NS_OK;
|
||||
if (!useCSS) {
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
IsTextPropertySetByContent(collapsedNode, aProperty, 0, 0,
|
||||
isSet, getter_AddRefs(resultNode));
|
||||
*aFirst = *aAny = *aAll = isSet;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// non-collapsed selection
|
||||
|
@ -983,18 +1094,42 @@ nsHTMLEditor::GetInlinePropertyBase(nsIAtom *aProperty,
|
|||
{
|
||||
if (node)
|
||||
{
|
||||
PRBool isSet;
|
||||
PRBool isSet = PR_FALSE;
|
||||
nsCOMPtr<nsIDOMNode>resultNode;
|
||||
if (first)
|
||||
{
|
||||
IsTextPropertySetByContent(node, aProperty, aAttribute, aValue, isSet, getter_AddRefs(resultNode), &firstValue);
|
||||
if (useCSS &&
|
||||
mHTMLCSSUtils->IsCSSEditableProperty(node, aProperty, aAttribute)) {
|
||||
// the HTML styles defined by aProperty/aAttribute has a CSS equivalence
|
||||
// in this implementation for node; let's check if it carries those css styles
|
||||
if (aValue) firstValue.Assign(*aValue);
|
||||
mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(node, aProperty, aAttribute,
|
||||
isSet, firstValue,
|
||||
COMPUTED_STYLE_TYPE);
|
||||
}
|
||||
else {
|
||||
IsTextPropertySetByContent(node, aProperty, aAttribute, aValue, isSet,
|
||||
getter_AddRefs(resultNode), &firstValue);
|
||||
}
|
||||
*aFirst = isSet;
|
||||
first = PR_FALSE;
|
||||
if (outValue) *outValue = firstValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsTextPropertySetByContent(node, aProperty, aAttribute, aValue, isSet, getter_AddRefs(resultNode), &theValue);
|
||||
if (useCSS &&
|
||||
mHTMLCSSUtils->IsCSSEditableProperty(node, aProperty, aAttribute)) {
|
||||
// the HTML styles defined by aProperty/aAttribute has a CSS equivalence
|
||||
// in this implementation for node; let's check if it carries those css styles
|
||||
if (aValue) firstValue.Assign(*aValue);
|
||||
mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(node, aProperty, aAttribute,
|
||||
isSet, theValue,
|
||||
COMPUTED_STYLE_TYPE);
|
||||
}
|
||||
else {
|
||||
IsTextPropertySetByContent(node, aProperty, aAttribute, aValue, isSet,
|
||||
getter_AddRefs(resultNode), &theValue);
|
||||
}
|
||||
if (firstValue != theValue)
|
||||
*aAll = PR_FALSE;
|
||||
}
|
||||
|
@ -1085,6 +1220,10 @@ nsresult nsHTMLEditor::RemoveInlinePropertyImpl(nsIAtom *aProperty, const nsARea
|
|||
|
||||
PRBool isCollapsed;
|
||||
selection->GetIsCollapsed(&isCollapsed);
|
||||
|
||||
PRBool useCSS;
|
||||
IsCSSEnabled(&useCSS);
|
||||
|
||||
if (isCollapsed)
|
||||
{
|
||||
// manipulating text attributes on a collapsed selection only sets state for the next text insertion
|
||||
|
@ -1142,6 +1281,32 @@ nsresult nsHTMLEditor::RemoveInlinePropertyImpl(nsIAtom *aProperty, const nsARea
|
|||
if ((startNode == endNode) && IsTextNode(startNode))
|
||||
{
|
||||
// we're done with this range!
|
||||
if (useCSS && mHTMLCSSUtils->IsCSSEditableProperty(startNode, aProperty, aAttribute)) {
|
||||
// the HTML style defined by aProperty/aAttribute has a CSS equivalence
|
||||
// in this implementation for startNode
|
||||
nsAutoString cssValue;
|
||||
PRBool isSet = PR_FALSE;
|
||||
mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(startNode,
|
||||
aProperty,
|
||||
aAttribute,
|
||||
isSet ,
|
||||
cssValue,
|
||||
COMPUTED_STYLE_TYPE);
|
||||
if (isSet) {
|
||||
// startNode's computed style indicates the CSS equivalence to the HTML style to
|
||||
// remove is applied; but we found no element in the ancestors of startNode
|
||||
// carrying specified styles; assume it comes from a rule and let's try to
|
||||
// insert a span "inverting" the style
|
||||
nsAutoString value; value.AssignWithConversion("-moz-editor-invert-value");
|
||||
PRInt32 startOffset, endOffset;
|
||||
range->GetStartOffset(&startOffset);
|
||||
range->GetEndOffset(&endOffset);
|
||||
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(startNode);
|
||||
if (mHTMLCSSUtils->IsCSSInvertable(aProperty, aAttribute)) {
|
||||
SetInlinePropertyOnTextNode(nodeAsText, startOffset, endOffset, aProperty, aAttribute, &value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1189,6 +1354,28 @@ nsresult nsHTMLEditor::RemoveInlinePropertyImpl(nsIAtom *aProperty, const nsARea
|
|||
node = do_QueryInterface(isupports);
|
||||
res = RemoveStyleInside(node, aProperty, aAttribute);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (useCSS && mHTMLCSSUtils->IsCSSEditableProperty(node, aProperty, aAttribute)) {
|
||||
// the HTML style defined by aProperty/aAttribute has a CSS equivalence
|
||||
// in this implementation for node
|
||||
nsAutoString cssValue;
|
||||
PRBool isSet = PR_FALSE;
|
||||
mHTMLCSSUtils->IsCSSEquivalentToHTMLInlineStyleSet(node,
|
||||
aProperty,
|
||||
aAttribute,
|
||||
isSet ,
|
||||
cssValue,
|
||||
COMPUTED_STYLE_TYPE);
|
||||
if (isSet) {
|
||||
// startNode's computed style indicates the CSS equivalence to the HTML style to
|
||||
// remove is applied; but we found no element in the ancestors of startNode
|
||||
// carrying specified styles; assume it comes from a rule and let's try to
|
||||
// insert a span "inverting" the style
|
||||
if (mHTMLCSSUtils->IsCSSInvertable(aProperty, aAttribute)) {
|
||||
nsAutoString value; value.AssignWithConversion("-moz-editor-invert-value");
|
||||
SetInlinePropertyOnNode(node, aProperty, aAttribute, &value);
|
||||
}
|
||||
}
|
||||
}
|
||||
arrayOfNodes->RemoveElementAt(0);
|
||||
}
|
||||
}
|
||||
|
@ -1239,6 +1426,21 @@ nsHTMLEditor::RelativeFontChange( PRInt32 aSizeChange)
|
|||
nsCOMPtr<nsIAtom> atom;
|
||||
if (aSizeChange==1) atom = nsIEditProperty::big;
|
||||
else atom = nsIEditProperty::small;
|
||||
|
||||
// Let's see in what kind of element the selection is
|
||||
PRInt32 offset;
|
||||
nsCOMPtr<nsIDOMNode> selectedNode;
|
||||
res = GetStartNodeAndOffset(selection, address_of(selectedNode), &offset);
|
||||
if (IsTextNode(selectedNode)) {
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
res = selectedNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
selectedNode = parent;
|
||||
}
|
||||
nsAutoString tag;
|
||||
atom->ToString(tag);
|
||||
if (!CanContainTag(selectedNode, tag)) return NS_OK;
|
||||
|
||||
// manipulating text attributes on a collapsed selection only sets state for the next text insertion
|
||||
return mTypeInState->SetProp(atom, nsAutoString(), nsAutoString());
|
||||
}
|
||||
|
@ -1388,6 +1590,11 @@ nsHTMLEditor::RelativeFontChangeOnTextNode( PRInt32 aSizeChange,
|
|||
if (aStartOffset == aEndOffset) return NS_OK;
|
||||
|
||||
nsresult res = NS_OK;
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
res = aTextNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!CanContainTag(parent, NS_LITERAL_STRING("big"))) return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> tmp, node = do_QueryInterface(aTextNode);
|
||||
|
||||
// do we need to split the text node?
|
||||
|
@ -1501,6 +1708,7 @@ nsHTMLEditor::RelativeFontChangeHelper( PRInt32 aSizeChange,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1656,3 +1864,19 @@ nsHTMLEditor::GetFontColorState(PRBool *aMixed, nsAWritableString &aOutColor)
|
|||
return res;
|
||||
}
|
||||
|
||||
// the return value is true only if the instance of the HTML editor we created
|
||||
// can handle CSS styles (for instance, Composer can, Messenger can't) and if
|
||||
// the CSS preference is checked
|
||||
nsresult
|
||||
nsHTMLEditor::IsCSSEnabled(PRBool *aIsSet)
|
||||
{
|
||||
*aIsSet = PR_FALSE;
|
||||
if (mCSSAware) {
|
||||
// TBD later : removal of mCSSAware and use only the presence of mHTMLCSSUtils
|
||||
if (mHTMLCSSUtils) {
|
||||
*aIsSet = mHTMLCSSUtils->IsCSSPrefChecked();
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -254,6 +255,15 @@ nsPlaintextEditor::EndEditorInit()
|
|||
return res;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPlaintextEditor::IsCSSEnabled(PRBool *aIsSet)
|
||||
{
|
||||
// STUB
|
||||
*aIsSet = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPlaintextEditor::SetDocumentCharacterSet(const nsAReadableString & characterSet)
|
||||
{
|
||||
|
@ -2104,3 +2114,11 @@ void nsPlaintextEditor::HandleEventListenerError()
|
|||
#pragma mark -
|
||||
#endif
|
||||
|
||||
nsresult
|
||||
nsPlaintextEditor::SetCSSEquivalentToHTMLStyle(nsIDOMElement * aElement,
|
||||
const nsAReadableString & aAttribute,
|
||||
const nsAReadableString & aValue)
|
||||
{
|
||||
// STUB
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
|
@ -106,6 +107,10 @@ public:
|
|||
|
||||
/* ------------ Overrides of nsEditor interface methods -------------- */
|
||||
NS_IMETHOD BeginComposition(nsTextEventReply* aReply);
|
||||
NS_IMETHOD IsCSSEnabled(PRBool *aIsSet);
|
||||
NS_IMETHOD SetCSSEquivalentToHTMLStyle(nsIDOMElement * aElement,
|
||||
const nsAReadableString & aAttribute,
|
||||
const nsAReadableString & aValue);
|
||||
|
||||
/** prepare the editor for use */
|
||||
NS_IMETHOD Init(nsIDOMDocument *aDoc, nsIPresShell *aPresShell, nsIContent *aRoot, nsISelectionController *aSelCon, PRUint32 aFlags);
|
||||
|
|
|
@ -1291,6 +1291,20 @@
|
|||
<FILEKIND>Library</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ChangeCSSInlineStyleTxn.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsHTMLCSSUtils.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
</FILELIST>
|
||||
<LINKORDER>
|
||||
<FILEREF>
|
||||
|
@ -1558,6 +1572,16 @@
|
|||
<PATH>UnicharUtilsStaticDebug.o</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ChangeCSSInlineStyleTxn.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsHTMLCSSUtils.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
</LINKORDER>
|
||||
</TARGET>
|
||||
<TARGET>
|
||||
|
@ -2791,6 +2815,20 @@
|
|||
<FILEKIND>Library</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ChangeCSSInlineStyleTxn.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsHTMLCSSUtils.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
</FILELIST>
|
||||
<LINKORDER>
|
||||
<FILEREF>
|
||||
|
@ -3053,6 +3091,16 @@
|
|||
<PATH>UnicharUtilsStatic.o</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ChangeCSSInlineStyleTxn.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsHTMLCSSUtils.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
</LINKORDER>
|
||||
</TARGET>
|
||||
<TARGET>
|
||||
|
@ -4202,6 +4250,20 @@
|
|||
<FILEKIND>Library</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ChangeCSSInlineStyleTxn.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsHTMLCSSUtils.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
</FILELIST>
|
||||
<LINKORDER>
|
||||
<FILEREF>
|
||||
|
@ -4404,6 +4466,16 @@
|
|||
<PATH>UnicharUtilsStaticDebug.o</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ChangeCSSInlineStyleTxn.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsHTMLCSSUtils.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
</LINKORDER>
|
||||
</TARGET>
|
||||
<TARGET>
|
||||
|
@ -5553,6 +5625,20 @@
|
|||
<FILEKIND>Library</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ChangeCSSInlineStyleTxn.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsHTMLCSSUtils.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
</FILELIST>
|
||||
<LINKORDER>
|
||||
<FILEREF>
|
||||
|
@ -5755,6 +5841,16 @@
|
|||
<PATH>UnicharUtilsStatic.o</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ChangeCSSInlineStyleTxn.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsHTMLCSSUtils.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
</LINKORDER>
|
||||
</TARGET>
|
||||
</TARGETLIST>
|
||||
|
@ -5774,6 +5870,12 @@
|
|||
<PATH>ChangeAttributeTxn.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>HTMLEditorDebug.shlb</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ChangeCSSInlineStyleTxn.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>HTMLEditorDebug.shlb</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
|
@ -5922,6 +6024,12 @@
|
|||
<PATH>nsEditProperty.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>HTMLEditorDebug.shlb</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>nsHTMLCSSUtils.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>HTMLEditorDebug.shlb</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
|
|
|
@ -75,3 +75,6 @@ pref("editor.history.url_maximum", 10);
|
|||
pref("editor.quotesPreformatted", true);
|
||||
|
||||
pref("editor.publish.", "");
|
||||
|
||||
pref("editor.use_css", false);
|
||||
pref("editor.css.default_length_unit", "px");
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
* Dan Haddix (dan6992@hotmail.com)
|
||||
* John Ratke (jratke@owc.net)
|
||||
* Ryan Cassin (rcassin@supernova.org)
|
||||
* Daniel Glazman (glazman@netscape.com)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -71,6 +72,7 @@ var gIsHTMLEditor = false;
|
|||
var gColorObj = new Object();
|
||||
var gDefaultTextColor = "";
|
||||
var gDefaultBackgroundColor = "";
|
||||
var gCSSPrefListener;
|
||||
var gPrefs;
|
||||
|
||||
// These must be kept in synch with the XUL <options> lists
|
||||
|
@ -78,6 +80,59 @@ var gFontSizeNames = new Array("xx-small","x-small","small","medium","large","x-
|
|||
|
||||
const nsIFilePicker = Components.interfaces.nsIFilePicker;
|
||||
|
||||
function nsButtonPrefListener()
|
||||
{
|
||||
try {
|
||||
var pbi = pref.QueryInterface(Components.interfaces.nsIPrefBranchInternal);
|
||||
pbi.addObserver(this.domain, this, false);
|
||||
} catch(ex) {
|
||||
dump("Failed to observe prefs: " + ex + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
// implements nsIObserver
|
||||
nsButtonPrefListener.prototype =
|
||||
{
|
||||
domain: "editor.use_css",
|
||||
observe: function(subject, topic, prefName)
|
||||
{
|
||||
dump("FOOOOO\n");
|
||||
// verify that we're changing a button pref
|
||||
if (topic != "nsPref:changed") return;
|
||||
if (prefName.substr(0, this.domain.length) != this.domain) return;
|
||||
|
||||
var button = document.getElementById("cmd_highlight");
|
||||
var mixedObj = new Object();
|
||||
if (button) {
|
||||
var prefs = GetPrefs();
|
||||
var useCSS = prefs.getBoolPref(prefName);
|
||||
if (useCSS) {
|
||||
button.removeAttribute("disabled");
|
||||
var state = editorShell.editor.QueryInterface(Components.interfaces.nsIHTMLEditor).GetHighlightColor(mixedObj);
|
||||
button.setAttribute("state", state);
|
||||
}
|
||||
else {
|
||||
button.setAttribute("disabled", "true");
|
||||
button.setAttribute("state", "transparent");
|
||||
}
|
||||
editorShell.CSSPrefChangedCallback(useCSS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function AfterHighlightColorChange()
|
||||
{
|
||||
var button = document.getElementById("cmd_highlight");
|
||||
var mixedObj = new Object();
|
||||
if (button) {
|
||||
var state = editorShell.editor.QueryInterface(Components.interfaces.nsIHTMLEditor).GetHighlightColor(mixedObj);
|
||||
button.setAttribute("state", state);
|
||||
onHighlightColorChange();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function EditorOnLoad()
|
||||
{
|
||||
// See if argument was passed.
|
||||
|
@ -241,6 +296,8 @@ function EditorStartup(editorType, editorElement)
|
|||
// such as file-related commands, HTML Source editing, Edit Modes...
|
||||
SetupComposerWindowCommands();
|
||||
|
||||
gCSSPrefListener = new nsButtonPrefListener();
|
||||
|
||||
// Get url for editor content and load it.
|
||||
// the editor gets instantiated by the editor shell when the URL has finished loading.
|
||||
var url = document.getElementById("args").getAttribute("value");
|
||||
|
@ -309,6 +366,7 @@ function EditorSharedStartup()
|
|||
// For new window, no default last-picked colors
|
||||
gColorObj.LastTextColor = "";
|
||||
gColorObj.LastBackgroundColor = "";
|
||||
gColorObj.LastHighlightColor = "";
|
||||
}
|
||||
|
||||
function _EditorNotImplemented()
|
||||
|
@ -777,6 +835,23 @@ function initFontSizeMenu(menuPopup)
|
|||
}
|
||||
}
|
||||
|
||||
function onHighlightColorChange()
|
||||
{
|
||||
var commandNode = document.getElementById("cmd_highlight");
|
||||
if (commandNode)
|
||||
{
|
||||
var color = commandNode.getAttribute("state");
|
||||
var button = document.getElementById("HighlightColorButton");
|
||||
if (button)
|
||||
{
|
||||
// No color set - get color set on page or other defaults
|
||||
if (!color)
|
||||
color = "transparent" ;
|
||||
|
||||
button.setAttribute("style", "background-color:"+color+" !important");
|
||||
}
|
||||
}
|
||||
}
|
||||
function onFontColorChange()
|
||||
{
|
||||
var commandNode = document.getElementById("cmd_fontColor");
|
||||
|
@ -861,7 +936,8 @@ function GetBackgroundElementWithColor()
|
|||
var element = window.editorShell.GetSelectedOrParentTableElement(tagNameObj, countObj);
|
||||
if (element && tagNameObj && tagNameObj.value)
|
||||
{
|
||||
gColorObj.BackgroundColor = element.getAttribute("bgcolor");
|
||||
gColorObj.BackgroundColor = GetHTMLOrCSSStyleValue(element, "bgcolor", "background-color");
|
||||
gColorObj.BackgroundColor = ConvertRGBColorIntoHEXColor(gColorObj.BackgroundColor);
|
||||
if (tagNameObj.value.toLowerCase() == "td")
|
||||
{
|
||||
gColorObj.Type = "Cell";
|
||||
|
@ -869,7 +945,8 @@ function GetBackgroundElementWithColor()
|
|||
|
||||
// Get any color that might be on parent table
|
||||
var table = GetParentTable(element);
|
||||
gColorObj.TableColor = table.getAttribute("bgcolor");
|
||||
gColorObj.TableColor = GetHTMLOrCSSStyleValue(table, "bgcolor", "background-color");
|
||||
gColorObj.TableColor = ConvertRGBColorIntoHEXColor(gColorObj.TableColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -879,11 +956,39 @@ function GetBackgroundElementWithColor()
|
|||
}
|
||||
else
|
||||
{
|
||||
element = GetBodyElement();
|
||||
var prefs = GetPrefs();
|
||||
var IsCSSPrefChecked = prefs.getBoolPref("editor.use_css");
|
||||
var element;
|
||||
if (IsCSSPrefChecked && editorShell.editorType == "html")
|
||||
{
|
||||
var selection = window.editorShell.editorSelection;
|
||||
if (selection)
|
||||
{
|
||||
element = selection.focusNode;
|
||||
while (!window.editorShell.NodeIsBlock(element))
|
||||
element = element.parentNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
element = GetBodyElement();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
element = GetBodyElement();
|
||||
}
|
||||
if (element)
|
||||
{
|
||||
gColorObj.Type = "Page";
|
||||
gColorObj.BackgroundColor = element.getAttribute("bgcolor");
|
||||
gColorObj.BackgroundColor = GetHTMLOrCSSStyleValue(element, "bgcolor", "background-color");
|
||||
if (gColorObj.BackgroundColor == "")
|
||||
{
|
||||
gColorObj.BackgroundColor = "transparent";
|
||||
}
|
||||
else
|
||||
{
|
||||
gColorObj.BackgroundColor = ConvertRGBColorIntoHEXColor(gColorObj.BackgroundColor);
|
||||
}
|
||||
gColorObj.PageColor = gColorObj.BackgroundColor;
|
||||
}
|
||||
}
|
||||
|
@ -926,6 +1031,20 @@ function EditorSelectColor(colorType, mouseEvent)
|
|||
else
|
||||
useLastColor = false;
|
||||
}
|
||||
else if (colorType == "Highlight")
|
||||
{
|
||||
gColorObj.Type = colorType;
|
||||
|
||||
// Get color from command node state
|
||||
commandNode = document.getElementById("cmd_highlight");
|
||||
currentColor = commandNode.getAttribute("state");
|
||||
gColorObj.HighlightColor = currentColor;
|
||||
|
||||
if (useLastColor && gColorObj.LastHighlightColor )
|
||||
gColorObj.HighlightColor = gColorObj.LastHighlightColor;
|
||||
else
|
||||
useLastColor = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
element = GetBackgroundElementWithColor();
|
||||
|
@ -980,7 +1099,7 @@ function EditorSelectColor(colorType, mouseEvent)
|
|||
return;
|
||||
}
|
||||
|
||||
if (colorType == "Text")
|
||||
if (gColorObj.Type == "Text")
|
||||
{
|
||||
if (currentColor != gColorObj.TextColor)
|
||||
{
|
||||
|
@ -992,9 +1111,21 @@ function EditorSelectColor(colorType, mouseEvent)
|
|||
// Update the command state (this will trigger color button update)
|
||||
goUpdateCommand("cmd_fontColor");
|
||||
}
|
||||
else if (gColorObj.Type == "Highlight")
|
||||
{
|
||||
if (currentColor != gColorObj.HighlightColor)
|
||||
{
|
||||
if (gColorObj.HighlightColor)
|
||||
window.editorShell.SetTextProperty("font", "bgcolor", gColorObj.HighlightColor);
|
||||
else
|
||||
window.editorShell.RemoveTextProperty("font", "bgcolor");
|
||||
}
|
||||
// Update the command state (this will trigger color button update)
|
||||
goUpdateCommand("cmd_highlight");
|
||||
}
|
||||
else if (element)
|
||||
{
|
||||
if (gColorObj.Type == "Table")
|
||||
if (false /*gColorObj.Type == "Table"*/)
|
||||
{
|
||||
// Set background on a table
|
||||
// Note that we shouldn't trust "currentColor" because of "TableOrCell" behavior
|
||||
|
@ -1024,7 +1155,7 @@ function EditorSelectColor(colorType, mouseEvent)
|
|||
{
|
||||
var defColors = GetDefaultBrowserColors();
|
||||
if (defColors)
|
||||
{
|
||||
{ // GLAZOU : this has to be changed
|
||||
if (!bodyelement.getAttribute("text"))
|
||||
window.editorShell.SetAttribute(bodyelement, "text", defColors.TextColor);
|
||||
|
||||
|
@ -2428,3 +2559,22 @@ function SwitchInsertCharToAnotherEditorOrClose()
|
|||
}
|
||||
}
|
||||
|
||||
function GetHTMLOrCSSStyleValue(element, attrName, cssPropertyName)
|
||||
{
|
||||
var prefs = GetPrefs();
|
||||
var IsCSSPrefChecked = prefs.getBoolPref("editor.use_css");
|
||||
var value;
|
||||
if (IsCSSPrefChecked && editorShell.editorType == "html")
|
||||
{
|
||||
value = element.style.getPropertyValue(cssPropertyName);
|
||||
if (value == "") {
|
||||
value = element.getAttribute(attrName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = element.getAttribute(attrName);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
@ -181,6 +181,10 @@
|
|||
<!-- from editorOverlay -->
|
||||
<menulist id="ParagraphSelect"/>
|
||||
<stack id="ColorButtons"/>
|
||||
<toolbarbutton id="HighlightColorButton"/>
|
||||
|
||||
<toolbarseparator class="toolbarseparator-standard"/>
|
||||
|
||||
<toolbarbutton id="DecreaseFontSizeButton"/>
|
||||
<toolbarbutton id="IncreaseFontSizeButton"/>
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
-
|
||||
- Contributor(s):
|
||||
- Ryan Cassin (rcassin@supernova.org)
|
||||
- Daniel Glazman (glazman@netscape.com)
|
||||
-->
|
||||
|
||||
<!DOCTYPE window SYSTEM "chrome://editor/locale/editorOverlay.dtd">
|
||||
|
@ -202,6 +203,7 @@
|
|||
<!-- No "oncommand", use EditorSelectColor() to bring up color dialog -->
|
||||
<command id="cmd_fontColor" state=""/>
|
||||
<command id="cmd_backgroundColor" state=""/>
|
||||
<command id="cmd_highlight" state="transparent" oncommand="EditorSelectColor('Highlight', event);"/>
|
||||
|
||||
<command id="cmd_fontSize" state="" oncommand="goDoCommand('cmd_fontSize')"/>
|
||||
<command id="cmd_align" state=""/>
|
||||
|
@ -748,6 +750,10 @@
|
|||
onclick="EditorSelectColor('Text', event);"
|
||||
tooltiptext="&TextColorButton.tooltip;"/>
|
||||
</stack>
|
||||
<toolbarbutton id="HighlightColorButton" tooltip="aTooltip"
|
||||
tooltiptext="&HighlightColorButton.tooltip;" command="cmd_highlight">
|
||||
<observes element="cmd_highlight" attribute="state" onbroadcast="onHighlightColorChange()"/>
|
||||
</toolbarbutton>
|
||||
|
||||
<!-- A BUG IN CSS/BOXES MAKES THIS ASSERT WHEN CLASS= IS PRESENT AND WE TRY TO COLLAPSE THE TOOLBOX -->
|
||||
<toolbarbutton id="DecreaseFontSizeButton" observes="cmd_decreaseFont"
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* Contributor(s):
|
||||
* Pete Collins
|
||||
* Brian King
|
||||
* Daniel Glazman <glazman@netscape.com>
|
||||
*/
|
||||
/*
|
||||
if we ever need to use a different string bundle, use srGetStrBundle
|
||||
|
@ -664,3 +665,43 @@ function GetOS()
|
|||
return gOS;
|
||||
}
|
||||
|
||||
function ConvertRGBColorIntoHEXColor(color)
|
||||
{
|
||||
if (color.search( /rgb.*/ ) != -1)
|
||||
{
|
||||
res = color.match( /rgb\((\d*),(\d*),(\d*)\)/ );
|
||||
r = Number(RegExp.$1).toString(16);
|
||||
if (r.length == 1) r = "0"+r;
|
||||
v = Number(RegExp.$2).toString(16);
|
||||
if (v.length == 1) v = "0"+v;
|
||||
b = Number(RegExp.$3).toString(16);
|
||||
if (b.length == 1) b = "0"+b;
|
||||
return "#"+r+v+b;
|
||||
}
|
||||
else
|
||||
{
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
function GetHTMLOrCSSStyleValue(element, attrName, cssPropertyName)
|
||||
{
|
||||
var prefs = GetPrefs();
|
||||
var IsCSSPrefChecked = prefs.getBoolPref("editor.use_css");
|
||||
var value;
|
||||
if (IsCSSPrefChecked && editorShell.editorType == "html")
|
||||
{
|
||||
value = element.style.getPropertyValue(cssPropertyName);
|
||||
if (value == "") {
|
||||
value = element.getAttribute(attrName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = element.getAttribute(attrName);
|
||||
}
|
||||
if (value == null) {
|
||||
value = "";
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<script type="application/x-javascript">
|
||||
<!-- Add "shouldAutoSave", "autoSaveAmount" to _elementIDs when implemented -->
|
||||
<![CDATA[
|
||||
var _elementIDs = ["maintainTableStructure", "preserveFormatting", "recentFiles"];
|
||||
var _elementIDs = ["maintainTableStructure", "preserveFormatting", "recentFiles", "useCSS"];
|
||||
]]>
|
||||
</script>
|
||||
<script type="application/x-javascript" src="chrome://editor/content/EdDialogCommon.js"/>
|
||||
|
@ -155,4 +155,16 @@
|
|||
|
||||
</groupbox>
|
||||
-->
|
||||
<groupbox>
|
||||
<caption label="&cssEditing.label;"/>
|
||||
<checkbox
|
||||
label = "&useCSS.label;"
|
||||
id = "useCSS"
|
||||
accesskey = ""
|
||||
pref = "true"
|
||||
preftype = "bool"
|
||||
prefstring= "editor.use_css"
|
||||
prefattribute="checked"
|
||||
/>
|
||||
</groupbox>
|
||||
</page>
|
||||
|
|
|
@ -101,7 +101,9 @@ SaveToUseRelativeUrl=Relative URLs can only be used on pages which have been sav
|
|||
NoNamedAnchors=(No named anchors in this page)
|
||||
NoHeadings=(No headings without anchors)
|
||||
TextColor=Text Color
|
||||
HighlightColor=Highlight Color
|
||||
PageColor=Page Background Color
|
||||
BlockColor=Block Background Color
|
||||
TableColor=Table Background Color
|
||||
CellColor=Cell Background Color
|
||||
TableOrCellColor=Table or Cell Color
|
||||
|
|
|
@ -595,6 +595,7 @@
|
|||
<!ENTITY TextColorButton.tooltip "Choose color for text">
|
||||
<!ENTITY BackgroundColorButton.tooltip "Choose color for background">
|
||||
<!ENTITY throbber.tooltip "Go to the &vendorShortName; home page">
|
||||
<!ENTITY HighlightColorButton.tooltip "Choose highlight color for text">
|
||||
|
||||
<!-- editor toolbar -->
|
||||
<!ENTITY decreaseFontSizeToolbarCmd.tooltip "Smaller font size">
|
||||
|
|
|
@ -31,3 +31,6 @@
|
|||
|
||||
<!ENTITY recentFiles.title "Recent Pages Menu">
|
||||
<!ENTITY documentsInMenu "Maximum number of pages listed:">
|
||||
|
||||
<!ENTITY cssEditing.label "CSS Editing">
|
||||
<!ENTITY useCSS.label "Use CSS (Cascading Style Sheets) styles instead of HTML elements and attributes">
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Daniel Glazman (glazman@netscape.com)
|
||||
*/
|
||||
|
||||
|
||||
|
@ -28,6 +29,7 @@ var gColor = "";
|
|||
var LastPickedColor = "";
|
||||
var ColorType = "Text";
|
||||
var TextType = false;
|
||||
var HighlightType = false;
|
||||
var TableOrCell = false;
|
||||
var LastPickedIsDefault = true;
|
||||
var NoDefault = false;
|
||||
|
@ -36,6 +38,8 @@ var gColorObj;
|
|||
// dialog initialization code
|
||||
function Startup()
|
||||
{
|
||||
// if (!InitEditorShell()) return;
|
||||
|
||||
if (!window.arguments[1])
|
||||
{
|
||||
dump("EdColorPicker: Missing color object param\n");
|
||||
|
@ -64,9 +68,17 @@ function Startup()
|
|||
ColorType = gColorObj.Type;
|
||||
// Get string for dialog title from passed-in type
|
||||
// (note constraint on editor.properties string name)
|
||||
window.title = GetString(ColorType+"Color");
|
||||
var prefs = GetPrefs();
|
||||
var IsCSSPrefChecked = prefs.getBoolPref("editor.use_css");
|
||||
if (ColorType == "Page" && IsCSSPrefChecked && editorShell.editorType == "html")
|
||||
{
|
||||
window.title = GetString("BlockColor");
|
||||
}
|
||||
else
|
||||
{
|
||||
window.title = GetString(ColorType+"Color");
|
||||
}
|
||||
}
|
||||
|
||||
if (!window.title)
|
||||
window.title = GetString("Color");
|
||||
|
||||
|
@ -107,6 +119,11 @@ function Startup()
|
|||
gDialog.CellRadio.focus();
|
||||
}
|
||||
break;
|
||||
case "Highlight":
|
||||
HighlightType = true;
|
||||
if (gColorObj.HighlightColor)
|
||||
gColor = gColorObj.HighlightColor;
|
||||
break;
|
||||
default:
|
||||
// Any other type will change some kind of text,
|
||||
TextType = true;
|
||||
|
@ -127,6 +144,12 @@ function Startup()
|
|||
gColorObj.LastTextColor = gDialog.LastPickedColor.getAttribute("LastTextColor");
|
||||
LastPickedColor = gColorObj.LastTextColor;
|
||||
}
|
||||
else if (HighlightType)
|
||||
{
|
||||
if ( !("LastHighlightColor" in gColorObj) || !gColorObj.LastHighlightColor)
|
||||
gColorObj.LastHighlightColor = gDialog.LastPickedColor.getAttribute("LastHighlightColor");
|
||||
LastPickedColor = gColorObj.LastHighlightColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !("LastBackgroundColor" in gColorObj) || !gColorObj.LastBackgroundColor)
|
||||
|
@ -265,6 +288,15 @@ function onAccept()
|
|||
gColorObj.LastTextColor = gColor;
|
||||
}
|
||||
}
|
||||
else if (HighlightType)
|
||||
{
|
||||
gColorObj.HighlightColor = gColor;
|
||||
if (gColor.length > 0)
|
||||
{
|
||||
gDialog.LastPickedColor.setAttribute("LastHighlightColor", gColor);
|
||||
gColorObj.LastHighlightColor = gColor;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gColorObj.BackgroundColor = gColor;
|
||||
|
|
|
@ -49,9 +49,12 @@ const vlinkStr = "vlink";
|
|||
const alinkStr = "alink";
|
||||
const bgcolorStr = "bgcolor";
|
||||
const backgroundStr = "background";
|
||||
const colorStyle = "color: ";
|
||||
const backColorStyle = "background-color: ";
|
||||
const backImageStyle = "; background-image: url(";
|
||||
const cssColorStr = "color";
|
||||
const cssBackgroundColorStr = "background-color";
|
||||
const cssBackgroundImageStr = "background-image";
|
||||
const colorStyle = cssColorStr + ": ";
|
||||
const backColorStyle = cssBackgroundColorStr + ": ";
|
||||
const backImageStyle = "; " + cssBackgroundImageStr + ": url(";
|
||||
|
||||
var customTextColor;
|
||||
var customLinkColor;
|
||||
|
@ -113,7 +116,12 @@ function Startup()
|
|||
function InitDialog()
|
||||
{
|
||||
// Get image from document
|
||||
backgroundImage = globalElement.getAttribute(backgroundStr);
|
||||
backgroundImage = GetHTMLOrCSSStyleValue(globalElement, backgroundStr, cssBackgroundImageStr);
|
||||
innerURL = backgroundImage.match( /url\((.*)\)/ ) ;
|
||||
if (innerURL)
|
||||
{
|
||||
backgroundImage = RegExp.$1;
|
||||
}
|
||||
if (backgroundImage)
|
||||
{
|
||||
gDialog.BackgroundImageInput.value = backgroundImage;
|
||||
|
@ -122,11 +130,13 @@ function InitDialog()
|
|||
|
||||
SetRelativeCheckbox();
|
||||
|
||||
customTextColor = globalElement.getAttribute(textStr);
|
||||
customTextColor = GetHTMLOrCSSStyleValue(globalElement, textStr, cssColorStr);
|
||||
customTextColor = ConvertRGBColorIntoHEXColor(customTextColor);
|
||||
customLinkColor = globalElement.getAttribute(linkStr);
|
||||
customActiveColor = globalElement.getAttribute(alinkStr);
|
||||
customVisitedColor = globalElement.getAttribute(vlinkStr);
|
||||
customBackgroundColor = globalElement.getAttribute(bgcolorStr);
|
||||
customBackgroundColor = GetHTMLOrCSSStyleValue(globalElement, bgcolorStr, cssBackgroundColorStr);
|
||||
customBackgroundColor = ConvertRGBColorIntoHEXColor(customBackgroundColor);
|
||||
|
||||
var haveCustomColor =
|
||||
customTextColor ||
|
||||
|
|
|
@ -515,11 +515,22 @@ function LimitStringLength(elementID, length)
|
|||
editField.value = stringIn.slice(0,length);
|
||||
}
|
||||
|
||||
function StripPxUnit(value)
|
||||
{
|
||||
var pxIndex = value.search(/px/);
|
||||
if (pxIndex > 0) {
|
||||
// Strip out the unit
|
||||
value = value.substr(0, pxIndex);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function InitPixelOrPercentMenulist(elementForAtt, elementInDoc, attribute, menulistID, defaultIndex)
|
||||
{
|
||||
if (!defaultIndex) defaultIndex = gPixel;
|
||||
|
||||
var size = elementForAtt.getAttribute(attribute);
|
||||
// var size = elementForAtt.getAttribute(attribute);
|
||||
var size = GetHTMLOrCSSStyleValue(elementForAtt, attribute, attribute)
|
||||
var menulist = document.getElementById(menulistID);
|
||||
var pixelItem;
|
||||
var percentItem;
|
||||
|
@ -538,8 +549,9 @@ function InitPixelOrPercentMenulist(elementForAtt, elementInDoc, attribute, menu
|
|||
percentItem = AppendStringToMenulist(menulist, GetAppropriatePercentString(elementForAtt, elementInDoc));
|
||||
if (size && size.length > 0)
|
||||
{
|
||||
// Search for a "%" character
|
||||
// Search for a "%" or "px"
|
||||
var percentIndex = size.search(/%/);
|
||||
var pxIndex = size.search(/px/);
|
||||
if (percentIndex > 0)
|
||||
{
|
||||
// Strip out the %
|
||||
|
@ -547,6 +559,12 @@ function InitPixelOrPercentMenulist(elementForAtt, elementInDoc, attribute, menu
|
|||
if (percentItem)
|
||||
menulist.selectedItem = percentItem;
|
||||
}
|
||||
else if (pxIndex > 0)
|
||||
{
|
||||
// Strip out the %
|
||||
size = size.substr(0, pxIndex);
|
||||
menulist.selectedItem = pixelItem;
|
||||
}
|
||||
else
|
||||
menulist.selectedItem = pixelItem;
|
||||
}
|
||||
|
|
|
@ -71,8 +71,10 @@ function Startup()
|
|||
// by AdvancedEdit(), which is shared by all property dialogs
|
||||
function InitDialog()
|
||||
{
|
||||
// Just to be confusing, "size" is used instead of height
|
||||
var height = globalElement.getAttribute("size");
|
||||
// Just to be confusing, "size" is used instead of height because it does
|
||||
// not accept % values, only pixels
|
||||
var height = GetHTMLOrCSSStyleValue(globalElement, "size", "height")
|
||||
height = StripPxUnit(height);
|
||||
if(!height) {
|
||||
height = 2; //Default value
|
||||
}
|
||||
|
@ -84,24 +86,21 @@ function InitDialog()
|
|||
// This sets contents of menulist (adds pixel and percent menuitems elements)
|
||||
gDialog.widthInput.value = InitPixelOrPercentMenulist(globalElement, hLineElement, "width","pixelOrPercentMenulist");
|
||||
|
||||
align = globalElement.getAttribute("align");
|
||||
if (!align)
|
||||
align = "";
|
||||
align = align.toLowerCase();
|
||||
var marginLeft = GetHTMLOrCSSStyleValue(globalElement, "align", "margin-left").toLowerCase();
|
||||
var marginRight = GetHTMLOrCSSStyleValue(globalElement, "align", "margin-right").toLowerCase();
|
||||
align = marginLeft + " " + marginRight;
|
||||
gDialog.centerAlign.checked = (align == "center center" || align == "auto auto");
|
||||
gDialog.rightAlign.checked = (align == "right right" || align == "auto 0px");
|
||||
gDialog.leftAlign.checked = (align == "left left" || align == "0px auto" || align == " ");
|
||||
|
||||
var selectedRadio = gDialog.centerAlign;
|
||||
var radioGroup = gDialog.centerAlign.radioGroup
|
||||
switch (align)
|
||||
{
|
||||
case "left":
|
||||
gDialog.alignGroup.selectedItem = gDialog.leftAlign;
|
||||
break;
|
||||
case "right":
|
||||
gDialog.alignGroup.selectedItem = gDialog.rightAlign;
|
||||
break;
|
||||
default:
|
||||
gDialog.alignGroup.selectedItem = gDialog.centerAlign;
|
||||
break;
|
||||
if (gDialog.centerAlign.checked) {
|
||||
gDialog.alignGroup.selectedItem = gDialog.centerAlign;
|
||||
}
|
||||
else if (gDialog.rightAlign.checked) {
|
||||
gDialog.alignGroup.selectedItem = gDialog.rightAlign;
|
||||
}
|
||||
else {
|
||||
gDialog.alignGroup.selectedItem = gDialog.leftAlign;
|
||||
}
|
||||
|
||||
// This is tricky! Since the "noshade" attribute doesn't always have a value,
|
||||
|
|
|
@ -185,7 +185,28 @@ function InitDialog()
|
|||
// set spacing editfields
|
||||
gDialog.imagelrInput.value = globalElement.getAttribute("hspace");
|
||||
gDialog.imagetbInput.value = globalElement.getAttribute("vspace");
|
||||
gDialog.border.value = globalElement.getAttribute("border");
|
||||
|
||||
// dialog.border.value = globalElement.getAttribute("border");
|
||||
bv = GetHTMLOrCSSStyleValue(globalElement, "border", "border-top-width");
|
||||
var pxIndex = bv.search(/px/);
|
||||
if (pxIndex > 0)
|
||||
{
|
||||
// Strip out the px
|
||||
bv = bv.substr(0, pxIndex);
|
||||
}
|
||||
else if (bv == "thin")
|
||||
{
|
||||
bv = "1";
|
||||
}
|
||||
else if (bv == "medium")
|
||||
{
|
||||
bv = "3";
|
||||
}
|
||||
else if (bv == "thick")
|
||||
{
|
||||
bv = "5";
|
||||
}
|
||||
gDialog.border.value = bv;
|
||||
|
||||
// Get alignment setting
|
||||
var align = globalElement.getAttribute("align");
|
||||
|
|
|
@ -30,6 +30,7 @@ var maxColumns = 10000;
|
|||
var maxPixels = 10000;
|
||||
var rows;
|
||||
var columns;
|
||||
var prefs = GetPrefs();
|
||||
|
||||
// dialog initialization code
|
||||
function Startup()
|
||||
|
@ -53,7 +54,10 @@ function Startup()
|
|||
|
||||
// Make a copy to use for AdvancedEdit
|
||||
globalElement = tableElement.cloneNode(false);
|
||||
|
||||
if (prefs.getBoolPref("editor.use_css") && (editorShell.editorType == "html")) {
|
||||
// only for Composer and not for htmlmail
|
||||
globalElement.setAttribute("style", "text-align: left;");
|
||||
}
|
||||
// Initialize all widgets with image attributes
|
||||
InitDialog();
|
||||
|
||||
|
|
|
@ -93,14 +93,15 @@ function InitDialog()
|
|||
BuildBulletStyleList();
|
||||
gDialog.StartingNumberInput.value = "";
|
||||
|
||||
var type = globalElement ? globalElement.getAttribute("type") : null;
|
||||
var type = globalElement ? GetHTMLOrCSSStyleValue(globalElement, "type", "list-style-type") : null;
|
||||
if (type)
|
||||
type = type.toLowerCase();
|
||||
|
||||
var index = 0;
|
||||
if (ListType == "ul")
|
||||
{
|
||||
if (type)
|
||||
{
|
||||
type = type.toLowerCase();
|
||||
if (type == "disc")
|
||||
index = 1;
|
||||
else if (type == "circle")
|
||||
|
@ -114,18 +115,23 @@ function InitDialog()
|
|||
switch (type)
|
||||
{
|
||||
case "1":
|
||||
case "decimal":
|
||||
index = 1;
|
||||
break;
|
||||
case "I":
|
||||
case "upper-roman":
|
||||
index = 2;
|
||||
break;
|
||||
case "i":
|
||||
case "lower-roman":
|
||||
index = 3;
|
||||
break;
|
||||
case "A":
|
||||
case "upper-alpha":
|
||||
index = 4;
|
||||
break;
|
||||
case "a":
|
||||
case "lower-alpha":
|
||||
index = 5;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ var bgcolor = "bgcolor";
|
|||
var TableColor;
|
||||
var CellColor;
|
||||
|
||||
const cssBackgroundColorStr = "background-color";
|
||||
|
||||
var rowCount = 1;
|
||||
var colCount = 1;
|
||||
var lastRowIndex;
|
||||
|
@ -81,6 +83,8 @@ var maxColumns = 1000;
|
|||
var selection;
|
||||
var CellDataChanged = false;
|
||||
var canDelete = false;
|
||||
var gPrefs = GetPrefs();
|
||||
var gUseCSS = true;
|
||||
|
||||
// dialog initialization code
|
||||
function Startup()
|
||||
|
@ -95,6 +99,15 @@ function Startup()
|
|||
gDialog.TableColumnsInput = document.getElementById("TableColumnsInput");
|
||||
gDialog.TableWidthInput = document.getElementById("TableWidthInput");
|
||||
gDialog.TableWidthUnits = document.getElementById("TableWidthUnits");
|
||||
gDialog.TableHeightInput = document.getElementById("TableHeightInput");
|
||||
gDialog.TableHeightUnits = document.getElementById("TableHeightUnits");
|
||||
if (!gPrefs.getBoolPref("editor.use_css") || (editorShell.editorType != "html")) {
|
||||
gUseCSS = false;
|
||||
tableHeightLabel = document.getElementById("TableHeightLabel");
|
||||
tableHeightLabel.parentNode.removeChild(tableHeightLabel);
|
||||
gDialog.TableHeightInput.parentNode.removeChild(gDialog.TableHeightInput);
|
||||
gDialog.TableHeightUnits.parentNode.removeChild(gDialog.TableHeightUnits);
|
||||
}
|
||||
gDialog.BorderWidthInput = document.getElementById("BorderWidthInput");
|
||||
gDialog.SpacingInput = document.getElementById("SpacingInput");
|
||||
gDialog.PaddingInput = document.getElementById("PaddingInput");
|
||||
|
@ -264,15 +277,20 @@ function InitDialog()
|
|||
gDialog.TableRowsInput.value = rowCount;
|
||||
gDialog.TableColumnsInput.value = colCount;
|
||||
gDialog.TableWidthInput.value = InitPixelOrPercentMenulist(globalTableElement, TableElement, "width", "TableWidthUnits", gPercent);
|
||||
if (gUseCSS) {
|
||||
gDialog.TableHeightInput.value = InitPixelOrPercentMenulist(globalTableElement, TableElement, "height",
|
||||
"TableHeightUnits", gPercent);
|
||||
}
|
||||
gDialog.BorderWidthInput.value = globalTableElement.border;
|
||||
gDialog.SpacingInput.value = globalTableElement.cellSpacing;
|
||||
gDialog.PaddingInput.value = globalTableElement.cellPadding;
|
||||
|
||||
//BUG: The align strings are converted: e.g., "center" becomes "Center";
|
||||
var halign = globalTableElement.align.toLowerCase();
|
||||
if (halign == centerStr)
|
||||
var marginLeft = GetHTMLOrCSSStyleValue(globalTableElement, "align", "margin-left");
|
||||
var marginRight = GetHTMLOrCSSStyleValue(globalTableElement, "align", "margin-right");
|
||||
var halign = marginLeft.toLowerCase() + " " + marginRight.toLowerCase();
|
||||
if (halign == "center center" || halign == "auto auto")
|
||||
gDialog.TableAlignList.selectedIndex = 1;
|
||||
else if (halign == rightStr)
|
||||
else if (halign == "right right" || halign == "auto 0px")
|
||||
gDialog.TableAlignList.selectedIndex = 2;
|
||||
else // Default = left
|
||||
gDialog.TableAlignList.selectedIndex = 0;
|
||||
|
@ -291,7 +309,8 @@ function InitDialog()
|
|||
}
|
||||
gDialog.TableCaptionList.selectedIndex = index;
|
||||
|
||||
TableColor = globalTableElement.bgColor;
|
||||
TableColor = GetHTMLOrCSSStyleValue(globalTableElement, bgcolor, cssBackgroundColorStr);
|
||||
TableColor = ConvertRGBColorIntoHEXColor(TableColor);
|
||||
SetColor("tableBackgroundCW", TableColor);
|
||||
|
||||
InitCellPanel();
|
||||
|
@ -329,7 +348,7 @@ function InitCellPanel()
|
|||
|
||||
alignWasChar = false;
|
||||
|
||||
var halign = globalCellElement.align.toLowerCase();
|
||||
var halign = GetHTMLOrCSSStyleValue(globalCellElement, "align", "text-align").toLowerCase();
|
||||
switch (halign)
|
||||
{
|
||||
case centerStr:
|
||||
|
@ -362,13 +381,17 @@ function InitCellPanel()
|
|||
gDialog.CellStyleCheckbox.checked = AdvancedEditUsed && previousIndex != gDialog.CellStyleList.selectedIndex;
|
||||
|
||||
previousIndex = gDialog.TextWrapList.selectedIndex;
|
||||
gDialog.TextWrapList.selectedIndex = globalCellElement.noWrap ? 1 : 0;
|
||||
if (GetHTMLOrCSSStyleValue(globalCellElement, "nowrap", "white-space") == "nowrap")
|
||||
gDialog.TextWrapList.selectedIndex = 1;
|
||||
else
|
||||
gDialog.TextWrapList.selectedIndex = 0;
|
||||
gDialog.TextWrapCheckbox.checked = AdvancedEditUsed && previousIndex != gDialog.TextWrapList.selectedIndex;
|
||||
|
||||
previousValue = CellColor;
|
||||
SetColor("cellBackgroundCW", globalCellElement.bgColor);
|
||||
gDialog.CellColorCheckbox.checked = AdvancedEditUsed && CellColor != globalCellElement.bgColor;
|
||||
CellColor = globalCellElement.bgColor;
|
||||
CellColor = GetHTMLOrCSSStyleValue(globalCellElement, bgcolor, cssBackgroundColorStr);
|
||||
CellColor = ConvertRGBColorIntoHEXColor(CellColor);
|
||||
SetColor("cellBackgroundCW", CellColor);
|
||||
gDialog.CellColorCheckbox.checked = AdvancedEditUsed && previousValue != CellColor;
|
||||
|
||||
// We want to set this true in case changes came
|
||||
// from Advanced Edit dialog session (must assume something changed)
|
||||
|
@ -816,6 +839,12 @@ function ValidateTableData()
|
|||
1, maxPixels, globalTableElement, "width");
|
||||
if (gValidationError) return false;
|
||||
|
||||
if (gUseCSS) {
|
||||
ValidateNumber(gDialog.TableHeightInput, gDialog.TableHeightUnits,
|
||||
1, maxPixels, globalTableElement, "height");
|
||||
if (gValidationError) return false;
|
||||
}
|
||||
|
||||
var border = ValidateNumber(gDialog.BorderWidthInput, null, 0, maxPixels, globalTableElement, "border");
|
||||
// TODO: Deal with "BORDER" without value issue
|
||||
if (gValidationError) return false;
|
||||
|
@ -950,7 +979,6 @@ function ChangeIntTextbox(textboxID, checkboxID)
|
|||
function CloneAttribute(destElement, srcElement, attr)
|
||||
{
|
||||
var value = srcElement.getAttribute(attr);
|
||||
|
||||
// Use editorShell methods since we are always
|
||||
// modifying a table in the document and
|
||||
// we need transaction system for undo
|
||||
|
|
|
@ -57,23 +57,20 @@
|
|||
<vbox id="TablePanel">
|
||||
<groupbox orient="horizontal"><caption label="&size.label;"/>
|
||||
<grid>
|
||||
<columns><column/><column/></columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<label value="&tableRows.label;"/>
|
||||
<textbox class="narrow" id="TableRowsInput" oninput="forceInteger(this.id);"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<label value="&tableColumns.label;"/>
|
||||
<textbox class="narrow" id="TableColumnsInput" oninput="forceInteger(this.id);"/>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
<spacer class="bigspacer"/>
|
||||
<grid>
|
||||
<columns><column/><column/><column flex="1"/></columns>
|
||||
<rows>
|
||||
<columns><column/><column/><column/><column/><column/></columns>
|
||||
<rows>
|
||||
<row align="center">
|
||||
<text class="label" value="&tableRows.label;"/>
|
||||
<textbox class="narrow" id="TableRowsInput" oninput="forceInteger(this.id);"/>
|
||||
<spring class="bigspacer"/>
|
||||
<text class="label" value="&tableHeight.label;" id="TableHeightLabel"/>
|
||||
<textbox class="narrow" id="TableHeightInput" oninput="forceInteger(this.id);"/>
|
||||
<menulist id="TableHeightUnits"/>
|
||||
</row>
|
||||
<row align="center">
|
||||
<text class="label" value="&tableColumns.label;"/>
|
||||
<textbox class="narrow" id="TableColumnsInput" oninput="forceInteger(this.id);"/>
|
||||
<spring class="bigspacer"/>
|
||||
<label value="&tableWidth.label;"/>
|
||||
<textbox class="narrow" id="TableWidthInput" oninput="forceInteger(this.id);"/>
|
||||
<menulist id="TableWidthUnits"/>
|
||||
|
|
|
@ -75,3 +75,6 @@ pref("editor.history.url_maximum", 10);
|
|||
pref("editor.quotesPreformatted", true);
|
||||
|
||||
pref("editor.publish.", "");
|
||||
|
||||
pref("editor.use_css", false);
|
||||
pref("editor.css.default_length_unit", "px");
|
||||
|
|
|
@ -473,3 +473,22 @@
|
|||
margin: 9px 2px 2px 9px;
|
||||
}
|
||||
|
||||
#HighlightColorButton {
|
||||
-moz-image-region: rect(260px 16px 272px 0px);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
#HighlightColorButton:hover {
|
||||
-moz-image-region: rect(260px 32px 272px 16px);
|
||||
}
|
||||
|
||||
#HighlightColorButton:hover:active {
|
||||
-moz-image-region: rect(260px 48px 272px 32px);
|
||||
}
|
||||
|
||||
#HighlightColorButton[disabled="true"],
|
||||
#HighlightColorButton[disabled="true"]:hover,
|
||||
#HighlightColorButton[disabled="true"]:hover:active {
|
||||
-moz-image-region: rect(260px 64px 272px 48px);
|
||||
}
|
||||
|
||||
|
|
Двоичные данные
themes/classic/editor/icons/btn2.gif
Двоичные данные
themes/classic/editor/icons/btn2.gif
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 2.1 KiB После Ширина: | Высота: | Размер: 3.1 KiB |
|
@ -494,3 +494,29 @@
|
|||
margin: 9px 2px 2px 9px;
|
||||
}
|
||||
|
||||
#HighlightColorButton > .toolbarbutton-icon {
|
||||
margin-right: 0px ! important ;
|
||||
}
|
||||
|
||||
#HighlightColorButton {
|
||||
-moz-image-region: rect(355px 44px 372px 22px);
|
||||
margin: 4px;
|
||||
border: 1px inset #5B7693;
|
||||
padding: 0px;
|
||||
width: 20px; height: 17px;
|
||||
}
|
||||
|
||||
#HighlightColorButton:hover {
|
||||
-moz-image-region: rect(355px 66px 372px 44px);
|
||||
}
|
||||
|
||||
#HighlightColorButton:hover:active {
|
||||
-moz-image-region: rect(355px 88px 372px 66px);
|
||||
}
|
||||
|
||||
|
||||
#HighlightColorButton[disabled="true"],
|
||||
#HighlightColorButton[disabled="true"]:hover,
|
||||
#HighlightColorButton[disabled="true"]:hover:active {
|
||||
-moz-image-region: rect(372px 22px 389px 0px);
|
||||
}
|
||||
|
|
Двоичные данные
themes/modern/editor/icons/btn2.gif
Двоичные данные
themes/modern/editor/icons/btn2.gif
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 13 KiB После Ширина: | Высота: | Размер: 15 KiB |
Загрузка…
Ссылка в новой задаче