fix for 187955: improvements to html fragment sink and paste code. Fixes problems seen with "Create table From Selection" and also with CF_HTML paste.

r=brade; sr=kin
This commit is contained in:
jfrancis%netscape.com 2003-03-23 20:45:47 +00:00
Родитель 6c0d0439e7
Коммит b8893ea45e
3 изменённых файлов: 83 добавлений и 13 удалений

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

@ -163,8 +163,6 @@ class nsHTMLFragmentContentSink2 : public nsHTMLFragmentContentSink
public: public:
nsHTMLFragmentContentSink2() { mHitSentinel = PR_TRUE; mSeenBody = PR_FALSE;} nsHTMLFragmentContentSink2() { mHitSentinel = PR_TRUE; mSeenBody = PR_FALSE;}
virtual ~nsHTMLFragmentContentSink2() {} virtual ~nsHTMLFragmentContentSink2() {}
NS_IMETHODIMP OpenHead(const nsIParserNode& aNode) { return OpenContainer(aNode); }
NS_IMETHODIMP CloseHead() { return CloseContainer(eHTMLTag_head); }
}; };
nsresult nsresult
@ -389,13 +387,13 @@ nsHTMLFragmentContentSink::CloseHTML()
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLFragmentContentSink::OpenHead(const nsIParserNode& aNode) nsHTMLFragmentContentSink::OpenHead(const nsIParserNode& aNode)
{ {
return NS_OK; return OpenContainer(aNode);
} }
NS_IMETHODIMP NS_IMETHODIMP
nsHTMLFragmentContentSink::CloseHead() nsHTMLFragmentContentSink::CloseHead()
{ {
return NS_OK; return CloseContainer(eHTMLTag_head);
} }
NS_IMETHODIMP NS_IMETHODIMP

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

@ -2112,11 +2112,13 @@ nsresult nsHTMLEditor::CreateDOMFragmentFromPaste(nsIDOMNSRange *aNSRange,
nsresult res = NS_OK; nsresult res = NS_OK;
// if we have context info, create a fragment for that // if we have context info, create a fragment for that
nsVoidArray tagStack;
nsCOMPtr<nsIDOMDocumentFragment> contextfrag;
nsCOMPtr<nsIDOMNode> contextLeaf, junk; nsCOMPtr<nsIDOMNode> contextLeaf, junk;
PRInt32 contextDepth = 0; PRInt32 contextDepth = 0;
if (aContextStr.Length()) if (aContextStr.Length())
{ {
res = ParseFragment(aContextStr, address_of(contextAsNode)); res = ParseFragment(aContextStr, tagStack, address_of(contextAsNode));
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_TRUE(contextAsNode, NS_ERROR_FAILURE); NS_ENSURE_TRUE(contextAsNode, NS_ERROR_FAILURE);
@ -2135,14 +2137,21 @@ nsresult nsHTMLEditor::CreateDOMFragmentFromPaste(nsIDOMNSRange *aNSRange,
} }
} }
// get the tagstack for the context
res = CreateTagStack(tagStack, contextLeaf);
if (NS_FAILED(res))
{
FreeTagStackStrings(tagStack);
return res;
}
// create fragment for pasted html // create fragment for pasted html
res = ParseFragment(aInputString, outFragNode); res = ParseFragment(aInputString, tagStack, outFragNode);
FreeTagStackStrings(tagStack);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_TRUE(*outFragNode, NS_ERROR_FAILURE); NS_ENSURE_TRUE(*outFragNode, NS_ERROR_FAILURE);
RemoveBodyAndHead(*outFragNode); RemoveBodyAndHead(*outFragNode);
if (contextAsNode) if (contextAsNode)
{ {
// unite the two trees // unite the two trees
@ -2174,8 +2183,12 @@ nsresult nsHTMLEditor::CreateDOMFragmentFromPaste(nsIDOMNSRange *aNSRange,
return res; return res;
} }
nsresult nsHTMLEditor::ParseFragment(const nsAString &aFragStr, nsCOMPtr<nsIDOMNode> *outNode)
nsresult nsHTMLEditor::ParseFragment(const nsAString & aFragStr, nsVoidArray &aTagStack, nsCOMPtr<nsIDOMNode> *outNode)
{ {
// figure out if we are parsing full context or not
PRBool bContext = (aTagStack.Count()==0);
// create the parser to do the conversion. // create the parser to do the conversion.
nsCOMPtr<nsIParser> parser; nsCOMPtr<nsIParser> parser;
nsresult res = nsComponentManager::CreateInstance(kCParserCID, nsnull, NS_GET_IID(nsIParser), nsresult res = nsComponentManager::CreateInstance(kCParserCID, nsnull, NS_GET_IID(nsIParser),
@ -2185,15 +2198,21 @@ nsresult nsHTMLEditor::ParseFragment(const nsAString &aFragStr, nsCOMPtr<nsIDOMN
// create the html fragment sink // create the html fragment sink
nsCOMPtr<nsIContentSink> sink; nsCOMPtr<nsIContentSink> sink;
sink = do_CreateInstance(NS_HTMLFRAGMENTSINK2_CONTRACTID); if (bContext)
sink = do_CreateInstance(NS_HTMLFRAGMENTSINK2_CONTRACTID);
else
sink = do_CreateInstance(NS_HTMLFRAGMENTSINK_CONTRACTID);
NS_ENSURE_TRUE(sink, NS_ERROR_FAILURE); NS_ENSURE_TRUE(sink, NS_ERROR_FAILURE);
nsCOMPtr<nsIHTMLFragmentContentSink> fragSink(do_QueryInterface(sink)); nsCOMPtr<nsIHTMLFragmentContentSink> fragSink(do_QueryInterface(sink));
NS_ENSURE_TRUE(fragSink, NS_ERROR_FAILURE); NS_ENSURE_TRUE(fragSink, NS_ERROR_FAILURE);
// parse the fragment // parse the fragment
parser->SetContentSink(sink); parser->SetContentSink(sink);
parser->Parse(aFragStr, 0, NS_LITERAL_CSTRING("text/html"), PR_FALSE, PR_TRUE, eDTDMode_fragment); if (bContext)
parser->Parse(aFragStr, (void*)0, NS_LITERAL_CSTRING("text/html"), PR_FALSE, PR_TRUE, eDTDMode_fragment);
else
parser->ParseFragment(aFragStr, 0, aTagStack, 0, NS_LITERAL_CSTRING("text/html"), eDTDMode_quirks);
// get the fragment node // get the fragment node
nsCOMPtr<nsIDOMDocumentFragment> contextfrag; nsCOMPtr<nsIDOMDocumentFragment> contextfrag;
res = fragSink->GetFragment(getter_AddRefs(contextfrag)); res = fragSink->GetFragment(getter_AddRefs(contextfrag));
@ -2203,6 +2222,57 @@ nsresult nsHTMLEditor::ParseFragment(const nsAString &aFragStr, nsCOMPtr<nsIDOMN
return res; return res;
} }
nsresult nsHTMLEditor::CreateTagStack(nsVoidArray &aTagStack, nsIDOMNode *aNode)
{
nsresult res = NS_OK;
nsCOMPtr<nsIDOMNode> node= aNode;
PRBool bSeenBody = PR_FALSE;
while (node)
{
if (nsTextEditUtils::IsBody(node))
bSeenBody = PR_TRUE;
nsCOMPtr<nsIDOMNode> temp = node;
PRUint16 nodeType;
node->GetNodeType(&nodeType);
if (nsIDOMNode::ELEMENT_NODE == nodeType)
{
nsAutoString tagName;
node->GetNodeName(tagName);
// XXX Wish we didn't have to allocate here
PRUnichar* name = ToNewUnicode(tagName);
if (!name)
return NS_ERROR_OUT_OF_MEMORY;
aTagStack.AppendElement(name);
// printf("%s\n",NS_LossyConvertUCS2toASCII(tagName).get());
}
res = temp->GetParentNode(getter_AddRefs(node));
NS_ENSURE_SUCCESS(res, res);
}
if (!bSeenBody)
{
PRUnichar* bodyname = ToNewUnicode(NS_LITERAL_STRING("BODY"));
aTagStack.AppendElement(bodyname);
}
return res;
}
void nsHTMLEditor::FreeTagStackStrings(nsVoidArray &tagStack)
{
PRInt32 count = tagStack.Count();
for (PRInt32 i = 0; i < count; i++)
{
PRUnichar* str = (PRUnichar*)tagStack.ElementAt(i);
if (str) {
nsCRT::free(str);
}
}
}
nsresult nsHTMLEditor::CreateListOfNodesToPaste(nsIDOMNode *aFragmentAsNode, nsresult nsHTMLEditor::CreateListOfNodesToPaste(nsIDOMNode *aFragmentAsNode,
nsCOMArray<nsIDOMNode>& outNodeList, nsCOMArray<nsIDOMNode>& outNodeList,

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

@ -680,11 +680,13 @@ protected:
nsCOMPtr<nsIDOMNode> *outFragNode, nsCOMPtr<nsIDOMNode> *outFragNode,
PRInt32 *outRangeStartHint, PRInt32 *outRangeStartHint,
PRInt32 *outRangeEndHint); PRInt32 *outRangeEndHint);
nsresult ParseFragment(const nsAString & aFragStr, nsCOMPtr<nsIDOMNode> *outNode); nsresult ParseFragment(const nsAString & aStr, nsVoidArray &aTagStack, nsCOMPtr<nsIDOMNode> *outNode);
nsresult CreateListOfNodesToPaste(nsIDOMNode *aFragmentAsNode, nsresult CreateListOfNodesToPaste(nsIDOMNode *aFragmentAsNode,
nsCOMArray<nsIDOMNode>& outNodeList, nsCOMArray<nsIDOMNode>& outNodeList,
PRInt32 aRangeStartHint, PRInt32 aRangeStartHint,
PRInt32 aRangeEndHint); PRInt32 aRangeEndHint);
nsresult CreateTagStack(nsVoidArray &aTagStack, nsIDOMNode *aNode);
void FreeTagStackStrings(nsVoidArray &tagStack);
nsresult GetListAndTableParents( PRBool aEnd, nsresult GetListAndTableParents( PRBool aEnd,
nsCOMArray<nsIDOMNode>& aListOfNodes, nsCOMArray<nsIDOMNode>& aListOfNodes,
nsCOMArray<nsIDOMNode>& outArray); nsCOMArray<nsIDOMNode>& outArray);