NS_IMETHODIMP
nsSelectionCommand::DoCommand(const char *aCommandName,
nsISupports *aCommandContext)
{
nsCOMPtr<nsIContentViewerEdit> contentEdit;
GetContentViewerEditFromContext(aCommandContext, getter_AddRefs(contentEdit));
NS_ENSURE_TRUE(contentEdit, NS_ERROR_NOT_INITIALIZED);
return DoClipboardCommand(aCommandName, contentEdit, nsnull);
}
nsresult
nsClipboardGetContentsCommand::DoClipboardCommand(const char *aCommandName, nsIContentViewerEdit* aEdit, nsICommandParams* aParams)
{
NS_ENSURE_ARG(aParams);
nsCAutoString mimeType("text/plain");
nsXPIDLCString format; // nsICommandParams needs to use nsACString
if (NS_SUCCEEDED(aParams->GetCStringValue("format", getter_Copies(format))))
mimeType.Assign(format);
PRBool selectionOnly = PR_FALSE;
aParams->GetBooleanValue("selection_only", &selectionOnly);
nsAutoString contents;
nsresult rv = aEdit->GetContents(mimeType.get(), selectionOnly, contents);
if (NS_FAILED(rv))
return rv;
return aParams->SetStringValue("result", contents);
}
NS_IMETHODIMP DocumentViewerImpl::GetContents(const char *mimeType, PRBool selectionOnly, nsAString& aOutValue)
{
aOutValue.Truncate();
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_INITIALIZED);
NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED);
// Now we have the selection. Make sure it's nonzero:
nsCOMPtr<nsISelection> sel;
if (selectionOnly) {
nsCopySupport::GetSelectionForCopy(mDocument, getter_AddRefs(sel));
NS_ENSURE_TRUE(sel, NS_ERROR_FAILURE);
PRBool isCollapsed;
sel->GetIsCollapsed(&isCollapsed);
if (isCollapsed)
return NS_OK;
}
// call the copy code
return nsCopySupport::GetContents(nsDependentCString(mimeType), 0, sel,
mDocument, aOutValue);
}
nsresult
nsCopySupport::GetContents(const nsACString& aMimeType, PRUint32 aFlags, nsISelection *aSel, nsIDocument *aDoc, nsAString& outdata)
{
nsresult rv = NS_OK;
nsCOMPtr<nsIDocumentEncoder> docEncoder;
nsCAutoString encoderContractID(NS_DOC_ENCODER_CONTRACTID_BASE);
encoderContractID.Append(aMimeType);
docEncoder = do_CreateInstance(encoderContractID.get());
NS_ENSURE_TRUE(docEncoder, NS_ERROR_FAILURE);
PRUint32 flags = aFlags | nsIDocumentEncoder::SkipInvisibleContent;
if (aMimeType.Equals("text/plain"))
flags |= nsIDocumentEncoder::OutputPreformatted;
NS_ConvertASCIItoUTF16 unicodeMimeType(aMimeType);
nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
NS_ASSERTION(domDoc, "Need a document");
rv = docEncoder->Init(domDoc, unicodeMimeType, flags);
if (NS_FAILED(rv)) return rv;
if (aSel)
{
rv = docEncoder->SetSelection(aSel);
if (NS_FAILED(rv)) return rv;
}
// encode the selection
return docEncoder->EncodeToString(outdata);
}
NS_IMETHODIMP
nsDocumentEncoder::EncodeToString(nsAString& aOutputString)
{
if (!mDocument)
return NS_ERROR_NOT_INITIALIZED;
aOutputString.Truncate();
nsString output;
static const size_t bufferSize = 2048;
if (!mCachedBuffer) {
mCachedBuffer = nsStringBuffer::Alloc(bufferSize);
}
NS_ASSERTION(!mCachedBuffer->IsReadonly(),
"DocumentEncoder shouldn't keep reference to non-readonly buffer!");
static_cast<PRUnichar*>(mCachedBuffer->Data())[0] = PRUnichar(0);
mCachedBuffer->ToString(0, output, PR_TRUE);
// output owns the buffer now!
mCachedBuffer = nsnull;
if (!mSerializer) {
nsCAutoString progId(NS_CONTENTSERIALIZER_CONTRACTID_PREFIX);
AppendUTF16toUTF8(mMimeType, progId);
mSerializer = do_CreateInstance(progId.get());
NS_ENSURE_TRUE(mSerializer, NS_ERROR_NOT_IMPLEMENTED);
}
nsresult rv = NS_OK;
nsCOMPtr<nsIAtom> charsetAtom;
if (!mCharset.IsEmpty()) {
if (!mCharsetConverterManager) {
mCharsetConverterManager = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
}
PRBool rewriteEncodingDeclaration = !(mSelection || mRange || mNode) && !(mFlags & OutputDontRewriteEncodingDeclaration);
mSerializer->Init(mFlags, mWrapColumn, mCharset.get(), mIsCopying, rewriteEncodingDeclaration);
if (mSelection) {
nsCOMPtr<nsIDOMRange> range;
PRInt32 i, count = 0;
rv = mSelection->GetRangeCount(&count);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> node, prevNode;
for (i = 0; i < count; i++) {
mSelection->GetRangeAt(i, getter_AddRefs(range));
// 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
range->GetStartContainer(getter_AddRefs(node));
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
if (node != prevNode) {
if (prevNode) {
nsCOMPtr<nsINode> 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);
rv = SerializeNodeStart(n, 0, -1, output);
NS_ENSURE_SUCCESS(rv, rv);
prevNode = node;
}
}
nsCOMPtr<nsIRange> r = do_QueryInterface(range);
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);
}
mSelection = nsnull;
} else if (mRange) {
rv = SerializeRangeToString(mRange, output);
mRange = nsnull;
} else if (mNode) {
rv = SerializeToStringRecursive(mNode, output, mNodeIsContainer);
mNode = nsnull;
} else {
rv = mSerializer->AppendDocumentStart(mDocument, output);
if (NS_SUCCEEDED(rv)) {
rv = SerializeToStringRecursive(mDocument, output, PR_FALSE);
}
}
NS_ENSURE_SUCCESS(rv, rv);
rv = mSerializer->Flush(output);
if (NS_SUCCEEDED(rv)) {
aOutputString.Append(output.get(), output.Length());
}
mCachedBuffer = nsStringBuffer::FromString(output);
// Try to cache the buffer.
if (mCachedBuffer && mCachedBuffer->StorageSize() == bufferSize &&
!mCachedBuffer->IsReadonly()) {
mCachedBuffer->AddRef();
} else {
mCachedBuffer = nsnull;
}
return rv;
}