22662, 16720: greatly improve formatting of html source for inserted html tags. r=jfrancis
git-svn-id: svn://10.0.0.236/trunk@58667 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
1b2ae3e812
commit
831fa6d5c7
@ -25,7 +25,7 @@
|
||||
#include "nsIContent.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gNoisy = PR_FALSE;
|
||||
static PRBool gNoisy = PR_TRUE;
|
||||
#else
|
||||
static const PRBool gNoisy = PR_FALSE;
|
||||
#endif
|
||||
@ -106,6 +106,9 @@ NS_IMETHODIMP InsertElementTxn::Do(void)
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!resultNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// Try to insert formatting whitespace for the new node:
|
||||
mEditor->InsertFormattingForNode(resultNode);
|
||||
|
||||
// only set selection to insertion point if editor gives permission
|
||||
PRBool bAdjustSelection;
|
||||
mEditor->ShouldTxnSetSelection(&bAdjustSelection);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -80,38 +80,20 @@ protected:
|
||||
nsresult ReturnInHeader(nsIDOMSelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset);
|
||||
nsresult ReturnInParagraph(nsIDOMSelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset, PRBool *aCancel, PRBool *aHandled);
|
||||
nsresult ReturnInListItem(nsIDOMSelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset);
|
||||
|
||||
// helper methods
|
||||
static PRBool IsHeader(nsIDOMNode *aNode);
|
||||
static PRBool IsParagraph(nsIDOMNode *aNode);
|
||||
static PRBool IsListItem(nsIDOMNode *aNode);
|
||||
static PRBool IsTableCell(nsIDOMNode *aNode);
|
||||
static PRBool IsList(nsIDOMNode *aNode);
|
||||
static PRBool IsUnorderedList(nsIDOMNode *aNode);
|
||||
static PRBool IsOrderedList(nsIDOMNode *aNode);
|
||||
static PRBool IsBlockquote(nsIDOMNode *aNode);
|
||||
static PRBool IsAnchor(nsIDOMNode *aNode);
|
||||
static PRBool IsImage(nsIDOMNode *aNode);
|
||||
static PRBool IsDiv(nsIDOMNode *aNode);
|
||||
static PRBool IsNormalDiv(nsIDOMNode *aNode);
|
||||
static PRBool IsMozDiv(nsIDOMNode *aNode);
|
||||
static PRBool IsMailCite(nsIDOMNode *aNode);
|
||||
|
||||
|
||||
nsresult IsEmptyBlock(nsIDOMNode *aNode,
|
||||
PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||
PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||
nsresult IsEmptyNode(nsIDOMNode *aNode,
|
||||
PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||
PRBool IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent);
|
||||
PRBool IsFirstNode(nsIDOMNode *aNode);
|
||||
PRBool IsLastNode(nsIDOMNode *aNode);
|
||||
PRBool AtStartOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);
|
||||
PRBool AtEndOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);
|
||||
|
||||
|
||||
nsresult GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode, PRInt32 aOffset,
|
||||
PRInt32 actionID, nsCOMPtr<nsIDOMNode> *outNode, PRInt32 *outOffset);
|
||||
nsresult GetPromotedRanges(nsIDOMSelection *inSelection,
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
|
||||
#include "nsHTMLEditor.h"
|
||||
#include "nsHTMLEditRules.h"
|
||||
#include "nsHTMLEditUtils.h"
|
||||
|
||||
#include "nsEditorEventListeners.h"
|
||||
|
||||
@ -3421,6 +3422,7 @@ nsHTMLEditor::GetEmbeddedObjects(nsISupportsArray** aNodeList)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::InsertFormattingForNode(nsIDOMNode* aNode)
|
||||
{
|
||||
return NS_OK;
|
||||
nsresult res;
|
||||
|
||||
// Don't insert any formatting unless it's an element node
|
||||
@ -3431,54 +3433,102 @@ nsHTMLEditor::InsertFormattingForNode(nsIDOMNode* aNode)
|
||||
if (nodeType != nsIDOMNode::ELEMENT_NODE)
|
||||
return NS_OK;
|
||||
|
||||
// Insert formatting only for block nodes
|
||||
// (would it be better to insert for any non-inline node?)
|
||||
PRBool block;
|
||||
res = IsNodeBlock(aNode, block);
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
if (!block)
|
||||
// Don't insert formatting if we're a plaintext editor.
|
||||
// The newlines get considered to be part of the text.
|
||||
// This, of course, makes the html look lousy, but we're expecting
|
||||
// that plaintext editors will only output plaintext, not html.
|
||||
if (mFlags & nsHTMLEditor::eEditorPlaintextMask)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
res = aNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
PRInt32 offset = GetIndexOf(parent, aNode);
|
||||
|
||||
nsString namestr;
|
||||
aNode->GetNodeName(namestr);
|
||||
|
||||
// Don't insert formatting for pre or br if we're a plaintext editor.
|
||||
// The newlines get considered to be part of the text, yet the
|
||||
// edit rules also insert breaks, so we end up with too much
|
||||
// vertical whitespace any time the user hits return.
|
||||
// This, of course, makes the html look lousy, but we're
|
||||
// expecting that no one will look at the html from a plaintext editor.
|
||||
if ((mFlags & nsHTMLEditor::eEditorPlaintextMask)
|
||||
&& (namestr.Equals("pre", PR_TRUE) || namestr.Equals("br", PR_TRUE)))
|
||||
return NS_OK;
|
||||
|
||||
#ifdef DEBUG_akkana
|
||||
#define DEBUG_formatting
|
||||
#endif
|
||||
#ifdef DEBUG_formatting
|
||||
nsString namestr;
|
||||
aNode->GetNodeName(namestr);
|
||||
//DumpContentTree();
|
||||
char* nodename = namestr.ToNewCString();
|
||||
printf("Inserting formatting for node <%s> at offset %d\n",
|
||||
nodename, offset);
|
||||
nodename, GetIndexOf(parent, aNode));
|
||||
#endif /* DEBUG_formatting */
|
||||
|
||||
// If it has children, first iterate over the children:
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
res = aNode->GetFirstChild(getter_AddRefs(child));
|
||||
if (NS_SUCCEEDED(res) && child)
|
||||
{
|
||||
#ifdef DEBUG_formatting
|
||||
printf("%s: Iterating over children\n", nodename);
|
||||
#endif /* DEBUG_formatting */
|
||||
|
||||
while (child)
|
||||
{
|
||||
#ifdef DEBUG_formatting
|
||||
printf("%s child\n", nodename);
|
||||
#endif /* DEBUG_formatting */
|
||||
InsertFormattingForNode(child);
|
||||
nsCOMPtr<nsIDOMNode> nextSib;
|
||||
child->GetNextSibling(getter_AddRefs(nextSib));
|
||||
child = nextSib;
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoString newline ("\n");
|
||||
|
||||
//
|
||||
// XXX Would be nice, ultimately, to format according to user prefs.
|
||||
//
|
||||
res = NS_OK;
|
||||
|
||||
PRInt32 offset = GetIndexOf(parent, aNode);
|
||||
|
||||
if (nsHTMLEditUtils::IsBreak(aNode) && !nsHTMLEditUtils::IsMozBR(aNode))
|
||||
{
|
||||
// After the close tag
|
||||
res = InsertNoneditableTextNode(parent, offset+1, newline);
|
||||
}
|
||||
|
||||
else if (nsEditor::IsBlockNode(aNode))
|
||||
{
|
||||
#ifdef DEBUG_formatting
|
||||
printf("Block node %s at offset %d\n-----------\n", nodename, offset);
|
||||
DumpContentTree();
|
||||
#endif /* DEBUG_formatting */
|
||||
if (!nsHTMLEditUtils::IsListItem(aNode))
|
||||
{
|
||||
// After the close tag
|
||||
InsertNoneditableTextNode(parent, offset+1, newline);
|
||||
#ifdef DEBUG_formatting
|
||||
printf("Now %s has offset %d\n-----------\n",
|
||||
nodename, GetIndexOf(parent, aNode));
|
||||
DumpContentTree();
|
||||
printf("----------------\n");
|
||||
#endif /* DEBUG_formatting */
|
||||
}
|
||||
|
||||
// Before the open tag
|
||||
res = InsertNoneditableTextNode(parent, offset, newline);
|
||||
#ifdef DEBUG_formatting
|
||||
printf("And NOW, %s has offset %d\n-----------\n", nodename, GetIndexOf(parent, aNode));
|
||||
DumpContentTree();
|
||||
printf("----------------\n");
|
||||
#endif /* DEBUG_formatting */
|
||||
}
|
||||
|
||||
// Some inline tags for which we might want formatting:
|
||||
else if (nsHTMLEditUtils::IsImage(aNode))
|
||||
{
|
||||
res = InsertNoneditableTextNode(parent, offset, newline);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_formatting
|
||||
Recycle(nodename);
|
||||
#endif /* DEBUG_akkana */
|
||||
|
||||
//
|
||||
// XXX We don't yet have a real formatter. As a cheap stopgap,
|
||||
// XXX just insert a newline before and after each newly inserted tag.
|
||||
//
|
||||
|
||||
nsAutoString str ("\n");
|
||||
|
||||
// After the close tag
|
||||
//res = InsertNoneditableTextNode(parent, offset+1, str);
|
||||
|
||||
// Before the open tag
|
||||
res = InsertNoneditableTextNode(parent, offset, str);
|
||||
#endif /* DEBUG_formatting */
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -3725,15 +3775,14 @@ NS_IMETHODIMP nsHTMLEditor::CanPaste(PRBool &aCanPaste)
|
||||
// add the HTML-editor only flavors
|
||||
if ((editorFlags & eEditorPlaintextMask) == 0)
|
||||
{
|
||||
|
||||
for (char** flavor = htmlEditorFlavors; *flavor; flavor++)
|
||||
for (char** htmlFlavor = htmlEditorFlavors; *htmlFlavor; htmlFlavor++)
|
||||
{
|
||||
nsCOMPtr<nsISupportsString> flavorString;
|
||||
nsComponentManager::CreateInstance(NS_SUPPORTS_STRING_PROGID, nsnull,
|
||||
NS_GET_IID(nsISupportsString), getter_AddRefs(flavorString));
|
||||
if (flavorString)
|
||||
{
|
||||
flavorString->SetData(*flavor);
|
||||
flavorString->SetData(*htmlFlavor);
|
||||
flavorsList->AppendElement(flavorString);
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include "nsTextEditRules.h"
|
||||
|
||||
#include "nsEditor.h"
|
||||
#include "nsHTMLEditUtils.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMNode.h"
|
||||
@ -322,7 +323,7 @@ nsTextEditRules::WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
if (NS_FAILED(res)) return res;
|
||||
// get prior node
|
||||
res = GetPriorHTMLNode(selNode, selOffset, &priorNode);
|
||||
if (NS_SUCCEEDED(res) && priorNode && IsMozBR(priorNode))
|
||||
if (NS_SUCCEEDED(res) && priorNode && nsHTMLEditUtils::IsMozBR(priorNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> block1, block2;
|
||||
if (mEditor->IsBlockNode(selNode)) block1 = selNode;
|
||||
@ -456,7 +457,7 @@ nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = GetPriorHTMLNode(selNode, selOffset, &nearNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nearNode && IsBreak(nearNode) && !IsMozBR(nearNode))
|
||||
if (nearNode && nsHTMLEditUtils::IsBreak(nearNode) && !nsHTMLEditUtils::IsMozBR(nearNode))
|
||||
{
|
||||
PRBool bIsLast;
|
||||
res = IsLastEditableChild(nearNode, &bIsLast);
|
||||
@ -483,7 +484,7 @@ nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
nsCOMPtr<nsIDOMNode> nextNode;
|
||||
res = GetNextHTMLNode(nearNode, &nextNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (IsMozBR(nextNode))
|
||||
if (nsHTMLEditUtils::IsMozBR(nextNode))
|
||||
{
|
||||
res = nsEditor::GetNodeLocation(nextNode, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
@ -1666,7 +1667,7 @@ nsTextEditRules::GetPriorHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outN
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
if (*outNode && !nsHTMLEditUtils::InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
@ -1685,7 +1686,7 @@ nsTextEditRules::GetPriorHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMP
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
if (*outNode && !nsHTMLEditUtils::InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
@ -1705,7 +1706,7 @@ nsTextEditRules::GetNextHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNo
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
if (*outNode && !nsHTMLEditUtils::InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
@ -1724,7 +1725,7 @@ nsTextEditRules::GetNextHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPt
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
if (*outNode && !nsHTMLEditUtils::InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
@ -1832,98 +1833,6 @@ nsTextEditRules::GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBody: true if node an html body node
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::IsBody(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsTextEditRules::IsBody");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "body")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBreak: true if node an html break node
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::IsBreak(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsTextEditRules::IsBreak");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "br")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsMozBR: true if node an html br node with type = _moz
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::IsMozBR(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsTextEditRules::IsMozBR");
|
||||
if (IsBreak(node) && HasMozAttr(node)) return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// HasMozAttr: true if node has type attribute = _moz
|
||||
// (used to indicate the div's and br's we use in
|
||||
// mail compose rules)
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::HasMozAttr(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsTextEditRules::HasMozAttr");
|
||||
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(node);
|
||||
if (elem)
|
||||
{
|
||||
nsAutoString typeAttrName("type");
|
||||
nsAutoString typeAttrVal;
|
||||
nsresult res = elem->GetAttribute(typeAttrName, typeAttrVal);
|
||||
typeAttrVal.ToLowerCase();
|
||||
if (NS_SUCCEEDED(res) && (typeAttrVal == "_moz"))
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// InBody: true if node is a descendant of the body
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::InBody(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsTextEditRules::InBody");
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
nsCOMPtr<nsIDOMNode> p = do_QueryInterface(node);
|
||||
|
||||
while (p && !IsBody(p))
|
||||
{
|
||||
if ( NS_FAILED(p->GetParentNode(getter_AddRefs(tmp))) || !tmp) // no parent, ran off top of tree
|
||||
return PR_FALSE;
|
||||
p = tmp;
|
||||
}
|
||||
if (p) return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// CreateMozBR: put a BR node with moz attribute at {aNode, aOffset}
|
||||
//
|
||||
|
||||
@ -219,13 +219,6 @@ protected:
|
||||
nsresult GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstChild);
|
||||
nsresult GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastChild);
|
||||
|
||||
static PRBool IsBody(nsIDOMNode *aNode);
|
||||
static PRBool IsBreak(nsIDOMNode *aNode);
|
||||
static PRBool IsMozBR(nsIDOMNode *aNode);
|
||||
static PRBool HasMozAttr(nsIDOMNode *aNode);
|
||||
|
||||
static PRBool InBody(nsIDOMNode *aNode);
|
||||
|
||||
nsresult CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode);
|
||||
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
#include "nsIContent.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
static PRBool gNoisy = PR_FALSE;
|
||||
static PRBool gNoisy = PR_TRUE;
|
||||
#else
|
||||
static const PRBool gNoisy = PR_FALSE;
|
||||
#endif
|
||||
@ -106,6 +106,9 @@ NS_IMETHODIMP InsertElementTxn::Do(void)
|
||||
if (NS_FAILED(result)) return result;
|
||||
if (!resultNode) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// Try to insert formatting whitespace for the new node:
|
||||
mEditor->InsertFormattingForNode(resultNode);
|
||||
|
||||
// only set selection to insertion point if editor gives permission
|
||||
PRBool bAdjustSelection;
|
||||
mEditor->ShouldTxnSetSelection(&bAdjustSelection);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -80,38 +80,20 @@ protected:
|
||||
nsresult ReturnInHeader(nsIDOMSelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset);
|
||||
nsresult ReturnInParagraph(nsIDOMSelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset, PRBool *aCancel, PRBool *aHandled);
|
||||
nsresult ReturnInListItem(nsIDOMSelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset);
|
||||
|
||||
// helper methods
|
||||
static PRBool IsHeader(nsIDOMNode *aNode);
|
||||
static PRBool IsParagraph(nsIDOMNode *aNode);
|
||||
static PRBool IsListItem(nsIDOMNode *aNode);
|
||||
static PRBool IsTableCell(nsIDOMNode *aNode);
|
||||
static PRBool IsList(nsIDOMNode *aNode);
|
||||
static PRBool IsUnorderedList(nsIDOMNode *aNode);
|
||||
static PRBool IsOrderedList(nsIDOMNode *aNode);
|
||||
static PRBool IsBlockquote(nsIDOMNode *aNode);
|
||||
static PRBool IsAnchor(nsIDOMNode *aNode);
|
||||
static PRBool IsImage(nsIDOMNode *aNode);
|
||||
static PRBool IsDiv(nsIDOMNode *aNode);
|
||||
static PRBool IsNormalDiv(nsIDOMNode *aNode);
|
||||
static PRBool IsMozDiv(nsIDOMNode *aNode);
|
||||
static PRBool IsMailCite(nsIDOMNode *aNode);
|
||||
|
||||
|
||||
nsresult IsEmptyBlock(nsIDOMNode *aNode,
|
||||
PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||
PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||
nsresult IsEmptyNode(nsIDOMNode *aNode,
|
||||
PRBool *outIsEmptyBlock,
|
||||
PRBool aMozBRDoesntCount = PR_FALSE,
|
||||
PRBool aListItemsNotEmpty = PR_FALSE);
|
||||
PRBool IsDescendantOf(nsIDOMNode *aNode, nsIDOMNode *aParent);
|
||||
PRBool IsFirstNode(nsIDOMNode *aNode);
|
||||
PRBool IsLastNode(nsIDOMNode *aNode);
|
||||
PRBool AtStartOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);
|
||||
PRBool AtEndOfBlock(nsIDOMNode *aNode, PRInt32 aOffset, nsIDOMNode *aBlock);
|
||||
|
||||
|
||||
nsresult GetPromotedPoint(RulesEndpoint aWhere, nsIDOMNode *aNode, PRInt32 aOffset,
|
||||
PRInt32 actionID, nsCOMPtr<nsIDOMNode> *outNode, PRInt32 *outOffset);
|
||||
nsresult GetPromotedRanges(nsIDOMSelection *inSelection,
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
|
||||
#include "nsHTMLEditor.h"
|
||||
#include "nsHTMLEditRules.h"
|
||||
#include "nsHTMLEditUtils.h"
|
||||
|
||||
#include "nsEditorEventListeners.h"
|
||||
|
||||
@ -3421,6 +3422,7 @@ nsHTMLEditor::GetEmbeddedObjects(nsISupportsArray** aNodeList)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::InsertFormattingForNode(nsIDOMNode* aNode)
|
||||
{
|
||||
return NS_OK;
|
||||
nsresult res;
|
||||
|
||||
// Don't insert any formatting unless it's an element node
|
||||
@ -3431,54 +3433,102 @@ nsHTMLEditor::InsertFormattingForNode(nsIDOMNode* aNode)
|
||||
if (nodeType != nsIDOMNode::ELEMENT_NODE)
|
||||
return NS_OK;
|
||||
|
||||
// Insert formatting only for block nodes
|
||||
// (would it be better to insert for any non-inline node?)
|
||||
PRBool block;
|
||||
res = IsNodeBlock(aNode, block);
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
if (!block)
|
||||
// Don't insert formatting if we're a plaintext editor.
|
||||
// The newlines get considered to be part of the text.
|
||||
// This, of course, makes the html look lousy, but we're expecting
|
||||
// that plaintext editors will only output plaintext, not html.
|
||||
if (mFlags & nsHTMLEditor::eEditorPlaintextMask)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parent;
|
||||
res = aNode->GetParentNode(getter_AddRefs(parent));
|
||||
if (NS_FAILED(res))
|
||||
return res;
|
||||
PRInt32 offset = GetIndexOf(parent, aNode);
|
||||
|
||||
nsString namestr;
|
||||
aNode->GetNodeName(namestr);
|
||||
|
||||
// Don't insert formatting for pre or br if we're a plaintext editor.
|
||||
// The newlines get considered to be part of the text, yet the
|
||||
// edit rules also insert breaks, so we end up with too much
|
||||
// vertical whitespace any time the user hits return.
|
||||
// This, of course, makes the html look lousy, but we're
|
||||
// expecting that no one will look at the html from a plaintext editor.
|
||||
if ((mFlags & nsHTMLEditor::eEditorPlaintextMask)
|
||||
&& (namestr.Equals("pre", PR_TRUE) || namestr.Equals("br", PR_TRUE)))
|
||||
return NS_OK;
|
||||
|
||||
#ifdef DEBUG_akkana
|
||||
#define DEBUG_formatting
|
||||
#endif
|
||||
#ifdef DEBUG_formatting
|
||||
nsString namestr;
|
||||
aNode->GetNodeName(namestr);
|
||||
//DumpContentTree();
|
||||
char* nodename = namestr.ToNewCString();
|
||||
printf("Inserting formatting for node <%s> at offset %d\n",
|
||||
nodename, offset);
|
||||
nodename, GetIndexOf(parent, aNode));
|
||||
#endif /* DEBUG_formatting */
|
||||
|
||||
// If it has children, first iterate over the children:
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
res = aNode->GetFirstChild(getter_AddRefs(child));
|
||||
if (NS_SUCCEEDED(res) && child)
|
||||
{
|
||||
#ifdef DEBUG_formatting
|
||||
printf("%s: Iterating over children\n", nodename);
|
||||
#endif /* DEBUG_formatting */
|
||||
|
||||
while (child)
|
||||
{
|
||||
#ifdef DEBUG_formatting
|
||||
printf("%s child\n", nodename);
|
||||
#endif /* DEBUG_formatting */
|
||||
InsertFormattingForNode(child);
|
||||
nsCOMPtr<nsIDOMNode> nextSib;
|
||||
child->GetNextSibling(getter_AddRefs(nextSib));
|
||||
child = nextSib;
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoString newline ("\n");
|
||||
|
||||
//
|
||||
// XXX Would be nice, ultimately, to format according to user prefs.
|
||||
//
|
||||
res = NS_OK;
|
||||
|
||||
PRInt32 offset = GetIndexOf(parent, aNode);
|
||||
|
||||
if (nsHTMLEditUtils::IsBreak(aNode) && !nsHTMLEditUtils::IsMozBR(aNode))
|
||||
{
|
||||
// After the close tag
|
||||
res = InsertNoneditableTextNode(parent, offset+1, newline);
|
||||
}
|
||||
|
||||
else if (nsEditor::IsBlockNode(aNode))
|
||||
{
|
||||
#ifdef DEBUG_formatting
|
||||
printf("Block node %s at offset %d\n-----------\n", nodename, offset);
|
||||
DumpContentTree();
|
||||
#endif /* DEBUG_formatting */
|
||||
if (!nsHTMLEditUtils::IsListItem(aNode))
|
||||
{
|
||||
// After the close tag
|
||||
InsertNoneditableTextNode(parent, offset+1, newline);
|
||||
#ifdef DEBUG_formatting
|
||||
printf("Now %s has offset %d\n-----------\n",
|
||||
nodename, GetIndexOf(parent, aNode));
|
||||
DumpContentTree();
|
||||
printf("----------------\n");
|
||||
#endif /* DEBUG_formatting */
|
||||
}
|
||||
|
||||
// Before the open tag
|
||||
res = InsertNoneditableTextNode(parent, offset, newline);
|
||||
#ifdef DEBUG_formatting
|
||||
printf("And NOW, %s has offset %d\n-----------\n", nodename, GetIndexOf(parent, aNode));
|
||||
DumpContentTree();
|
||||
printf("----------------\n");
|
||||
#endif /* DEBUG_formatting */
|
||||
}
|
||||
|
||||
// Some inline tags for which we might want formatting:
|
||||
else if (nsHTMLEditUtils::IsImage(aNode))
|
||||
{
|
||||
res = InsertNoneditableTextNode(parent, offset, newline);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_formatting
|
||||
Recycle(nodename);
|
||||
#endif /* DEBUG_akkana */
|
||||
|
||||
//
|
||||
// XXX We don't yet have a real formatter. As a cheap stopgap,
|
||||
// XXX just insert a newline before and after each newly inserted tag.
|
||||
//
|
||||
|
||||
nsAutoString str ("\n");
|
||||
|
||||
// After the close tag
|
||||
//res = InsertNoneditableTextNode(parent, offset+1, str);
|
||||
|
||||
// Before the open tag
|
||||
res = InsertNoneditableTextNode(parent, offset, str);
|
||||
#endif /* DEBUG_formatting */
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -3725,15 +3775,14 @@ NS_IMETHODIMP nsHTMLEditor::CanPaste(PRBool &aCanPaste)
|
||||
// add the HTML-editor only flavors
|
||||
if ((editorFlags & eEditorPlaintextMask) == 0)
|
||||
{
|
||||
|
||||
for (char** flavor = htmlEditorFlavors; *flavor; flavor++)
|
||||
for (char** htmlFlavor = htmlEditorFlavors; *htmlFlavor; htmlFlavor++)
|
||||
{
|
||||
nsCOMPtr<nsISupportsString> flavorString;
|
||||
nsComponentManager::CreateInstance(NS_SUPPORTS_STRING_PROGID, nsnull,
|
||||
NS_GET_IID(nsISupportsString), getter_AddRefs(flavorString));
|
||||
if (flavorString)
|
||||
{
|
||||
flavorString->SetData(*flavor);
|
||||
flavorString->SetData(*htmlFlavor);
|
||||
flavorsList->AppendElement(flavorString);
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include "nsTextEditRules.h"
|
||||
|
||||
#include "nsEditor.h"
|
||||
#include "nsHTMLEditUtils.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMNode.h"
|
||||
@ -322,7 +323,7 @@ nsTextEditRules::WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel)
|
||||
if (NS_FAILED(res)) return res;
|
||||
// get prior node
|
||||
res = GetPriorHTMLNode(selNode, selOffset, &priorNode);
|
||||
if (NS_SUCCEEDED(res) && priorNode && IsMozBR(priorNode))
|
||||
if (NS_SUCCEEDED(res) && priorNode && nsHTMLEditUtils::IsMozBR(priorNode))
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> block1, block2;
|
||||
if (mEditor->IsBlockNode(selNode)) block1 = selNode;
|
||||
@ -456,7 +457,7 @@ nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = GetPriorHTMLNode(selNode, selOffset, &nearNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (nearNode && IsBreak(nearNode) && !IsMozBR(nearNode))
|
||||
if (nearNode && nsHTMLEditUtils::IsBreak(nearNode) && !nsHTMLEditUtils::IsMozBR(nearNode))
|
||||
{
|
||||
PRBool bIsLast;
|
||||
res = IsLastEditableChild(nearNode, &bIsLast);
|
||||
@ -483,7 +484,7 @@ nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
|
||||
nsCOMPtr<nsIDOMNode> nextNode;
|
||||
res = GetNextHTMLNode(nearNode, &nextNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (IsMozBR(nextNode))
|
||||
if (nsHTMLEditUtils::IsMozBR(nextNode))
|
||||
{
|
||||
res = nsEditor::GetNodeLocation(nextNode, &selNode, &selOffset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
@ -1666,7 +1667,7 @@ nsTextEditRules::GetPriorHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outN
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
if (*outNode && !nsHTMLEditUtils::InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
@ -1685,7 +1686,7 @@ nsTextEditRules::GetPriorHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMP
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
if (*outNode && !nsHTMLEditUtils::InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
@ -1705,7 +1706,7 @@ nsTextEditRules::GetNextHTMLNode(nsIDOMNode *inNode, nsCOMPtr<nsIDOMNode> *outNo
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
if (*outNode && !nsHTMLEditUtils::InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
@ -1724,7 +1725,7 @@ nsTextEditRules::GetNextHTMLNode(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPt
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// if it's not in the body, then zero it out
|
||||
if (*outNode && !InBody(*outNode))
|
||||
if (*outNode && !nsHTMLEditUtils::InBody(*outNode))
|
||||
{
|
||||
*outNode = nsnull;
|
||||
}
|
||||
@ -1832,98 +1833,6 @@ nsTextEditRules::GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBody: true if node an html body node
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::IsBody(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsTextEditRules::IsBody");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "body")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsBreak: true if node an html break node
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::IsBreak(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsTextEditRules::IsBreak");
|
||||
nsAutoString tag;
|
||||
nsEditor::GetTagString(node,tag);
|
||||
tag.ToLowerCase();
|
||||
if (tag == "br")
|
||||
{
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// IsMozBR: true if node an html br node with type = _moz
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::IsMozBR(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null node passed to nsTextEditRules::IsMozBR");
|
||||
if (IsBreak(node) && HasMozAttr(node)) return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// HasMozAttr: true if node has type attribute = _moz
|
||||
// (used to indicate the div's and br's we use in
|
||||
// mail compose rules)
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::HasMozAttr(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsTextEditRules::HasMozAttr");
|
||||
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(node);
|
||||
if (elem)
|
||||
{
|
||||
nsAutoString typeAttrName("type");
|
||||
nsAutoString typeAttrVal;
|
||||
nsresult res = elem->GetAttribute(typeAttrName, typeAttrVal);
|
||||
typeAttrVal.ToLowerCase();
|
||||
if (NS_SUCCEEDED(res) && (typeAttrVal == "_moz"))
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// InBody: true if node is a descendant of the body
|
||||
//
|
||||
PRBool
|
||||
nsTextEditRules::InBody(nsIDOMNode *node)
|
||||
{
|
||||
NS_PRECONDITION(node, "null parent passed to nsTextEditRules::InBody");
|
||||
nsCOMPtr<nsIDOMNode> tmp;
|
||||
nsCOMPtr<nsIDOMNode> p = do_QueryInterface(node);
|
||||
|
||||
while (p && !IsBody(p))
|
||||
{
|
||||
if ( NS_FAILED(p->GetParentNode(getter_AddRefs(tmp))) || !tmp) // no parent, ran off top of tree
|
||||
return PR_FALSE;
|
||||
p = tmp;
|
||||
}
|
||||
if (p) return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// CreateMozBR: put a BR node with moz attribute at {aNode, aOffset}
|
||||
//
|
||||
|
||||
@ -219,13 +219,6 @@ protected:
|
||||
nsresult GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstChild);
|
||||
nsresult GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastChild);
|
||||
|
||||
static PRBool IsBody(nsIDOMNode *aNode);
|
||||
static PRBool IsBreak(nsIDOMNode *aNode);
|
||||
static PRBool IsMozBR(nsIDOMNode *aNode);
|
||||
static PRBool HasMozAttr(nsIDOMNode *aNode);
|
||||
|
||||
static PRBool InBody(nsIDOMNode *aNode);
|
||||
|
||||
nsresult CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode);
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user