Bug 137450 - Problem copying and pasting a table from a web page to excel. r=bz

This commit is contained in:
lwz 2012-05-16 12:39:54 -04:00
parent b8c26d76b5
commit 32d78b6bbb

View File

@ -130,6 +130,11 @@ protected:
nsAString& aString);
nsresult SerializeRangeContextEnd(const nsTArray<nsINode*>& aAncestorArray,
nsAString& aString);
virtual PRInt32
GetImmediateContextCount(const nsTArray<nsINode*>& aAncestorArray)
{
return -1;
}
nsresult FlushText(nsAString& aString, bool aForce);
@ -185,6 +190,9 @@ protected:
nsAutoTArray<nsIContent*, 8> mEndNodes;
nsAutoTArray<PRInt32, 8> mEndOffsets;
bool mHaltRangeHint;
// HTML context has already been serialized for
// table cell selections (where parent is <tr>)
bool mContextAlreadySerialized;
bool mIsCopying; // Set to true only while copying
bool mNodeIsContainer;
nsStringBuffer* mCachedBuffer;
@ -232,6 +240,7 @@ void nsDocumentEncoder::Initialize(bool aClearCachedSerializer)
mStartRootIndex = 0;
mEndRootIndex = 0;
mHaltRangeHint = false;
mContextAlreadySerialized = false;
mNodeIsContainer = false;
if (aClearCachedSerializer) {
mSerializer = nsnull;
@ -913,16 +922,23 @@ nsresult
nsDocumentEncoder::SerializeRangeContextStart(const nsTArray<nsINode*>& aAncestorArray,
nsAString& aString)
{
PRInt32 i = aAncestorArray.Length();
if (mContextAlreadySerialized) {
return NS_OK;
}
PRInt32 i = aAncestorArray.Length(), j;
nsresult rv = NS_OK;
// currently only for table-related elements; see Bug 137450
j = GetImmediateContextCount(aAncestorArray);
while (i > 0) {
nsINode *node = aAncestorArray.ElementAt(--i);
if (!node)
break;
if (IncludeInContext(node)) {
// Either a general inclusion or as immediate context
if (IncludeInContext(node) || i < j) {
rv = SerializeNodeStart(node, 0, -1, aString);
if (NS_FAILED(rv))
@ -937,17 +953,24 @@ nsresult
nsDocumentEncoder::SerializeRangeContextEnd(const nsTArray<nsINode*>& aAncestorArray,
nsAString& aString)
{
PRInt32 i = 0;
if (mContextAlreadySerialized) {
return NS_OK;
}
PRInt32 i = 0, j;
PRInt32 count = aAncestorArray.Length();
nsresult rv = NS_OK;
// currently only for table-related elements
j = GetImmediateContextCount(aAncestorArray);
while (i < count) {
nsINode *node = aAncestorArray.ElementAt(i++);
if (!node)
break;
if (IncludeInContext(node)) {
// Either a general inclusion or as immediate context
if (IncludeInContext(node) || i - 1 < j) {
rv = SerializeNodeEnd(node, aString);
if (NS_FAILED(rv))
@ -1083,21 +1106,44 @@ nsDocumentEncoder::EncodeToString(nsAString& aOutputString)
// Bug 236546: newlines not added when copying table cells into clipboard
// Each selected cell shows up as a range containing a row with a single cell
// get the row, compare it to previous row and emit </tr><tr> as needed
// Bug 137450: Problem copying/pasting a table from a web page to Excel.
// Each separate block of <tr></tr> produced above will be wrapped by the
// immediate context. This assumes that you can't select cells that are
// multiple selections from two tables simultaneously.
range->GetStartContainer(getter_AddRefs(node));
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
if (node != prevNode) {
nsCOMPtr<nsINode> p;
if (prevNode) {
nsCOMPtr<nsINode> p = do_QueryInterface(prevNode);
p = do_QueryInterface(prevNode);
rv = SerializeNodeEnd(p, output);
NS_ENSURE_SUCCESS(rv, rv);
prevNode = nsnull;
}
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
if (content && content->Tag() == nsGkAtoms::tr) {
nsCOMPtr<nsINode> n = do_QueryInterface(node);
if (content && content->IsHTML(nsGkAtoms::tr)) {
nsINode* n = content;
if (!prevNode) {
// Went from a non-<tr> to a <tr>
mCommonAncestors.Clear();
nsContentUtils::GetAncestors(n->GetNodeParent(), mCommonAncestors);
rv = SerializeRangeContextStart(mCommonAncestors, output);
NS_ENSURE_SUCCESS(rv, rv);
// Don't let SerializeRangeToString serialize the context again
mContextAlreadySerialized = true;
}
rv = SerializeNodeStart(n, 0, -1, output);
NS_ENSURE_SUCCESS(rv, rv);
prevNode = node;
} else if (prevNode) {
// Went from a <tr> to a non-<tr>
mCommonAncestors.Clear();
nsContentUtils::GetAncestors(p->GetNodeParent(), mCommonAncestors);
rv = SerializeRangeContextEnd(mCommonAncestors, output);
NS_ENSURE_SUCCESS(rv, rv);
// Allow output of context again
mContextAlreadySerialized = false;
prevNode = nsnull;
}
}
@ -1105,12 +1151,21 @@ nsDocumentEncoder::EncodeToString(nsAString& aOutputString)
rv = SerializeRangeToString(r, output);
NS_ENSURE_SUCCESS(rv, rv);
}
if (prevNode) {
nsCOMPtr<nsINode> p = do_QueryInterface(prevNode);
rv = SerializeNodeEnd(p, output);
NS_ENSURE_SUCCESS(rv, rv);
mCommonAncestors.Clear();
nsContentUtils::GetAncestors(p->GetNodeParent(), mCommonAncestors);
rv = SerializeRangeContextEnd(mCommonAncestors, output);
NS_ENSURE_SUCCESS(rv, rv);
}
// could have been placed into the above if-loop
// but put outside to be safe
mContextAlreadySerialized = false;
mSelection = nsnull;
} else if (mRange) {
rv = SerializeRangeToString(mRange, output);
@ -1262,6 +1317,8 @@ protected:
bool IsLastNode(nsIDOMNode *aNode);
bool IsEmptyTextContent(nsIDOMNode* aNode);
virtual bool IncludeInContext(nsINode *aNode);
virtual PRInt32
GetImmediateContextCount(const nsTArray<nsINode*>& aAncestorArray);
bool mIsTextWidget;
};
@ -1975,3 +2032,26 @@ NS_NewHTMLCopyTextEncoder(nsIDocumentEncoder** aResult)
NS_ADDREF(*aResult);
return NS_OK;
}
PRInt32
nsHTMLCopyEncoder::GetImmediateContextCount(const nsTArray<nsINode*>& aAncestorArray)
{
PRInt32 i = aAncestorArray.Length(), j = 0;
while (j < i) {
nsINode *node = aAncestorArray.ElementAt(j);
if (!node) {
break;
}
nsCOMPtr<nsIContent> content(do_QueryInterface(node));
if (!content || !content->IsHTML() || content->Tag() != nsGkAtoms::tr &&
content->Tag() != nsGkAtoms::thead &&
content->Tag() != nsGkAtoms::tbody &&
content->Tag() != nsGkAtoms::tfoot &&
content->Tag() != nsGkAtoms::table) {
break;
}
++j;
}
return j;
}