LCOV - app.info - editor/libeditor/text/nsPlaintextDataTransfer.cpp

LCOV - code coverage report
| Current view: | directory - editor/libeditor/text - nsPlaintextDataTransfer.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 179 | 0 | 0.0 %
| Date: | 2012-04-21 | Functions: | 9 | 0 | 0.0 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozilla.org code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * Netscape Communications Corporation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *
          24                 :  * Alternatively, the contents of this file may be used under the terms of
          25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          28                 :  * of those above. If you wish to allow use of your version of this file only
          29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          30                 :  * use your version of this file under the terms of the MPL, indicate your
          31                 :  * decision by deleting the provisions above and replace them with the notice
          32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          33                 :  * the provisions above, a recipient may use your version of this file under
          34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          35                 :  *
          36                 :  * ***** END LICENSE BLOCK ***** */
          37                 :
          38                 : #include "mozilla/Util.h"
          39                 :
          40                 : #include "nsPlaintextEditor.h"
          41                 :
          42                 : #include "nsIDOMDocument.h"
          43                 : #include "nsIDocument.h"
          44                 : #include "nsIContent.h"
          45                 : #include "nsIFormControl.h"
          46                 : #include "nsIDOMEventTarget.h"
          47                 : #include "nsIDOMNSEvent.h"
          48                 : #include "nsIDOMMouseEvent.h"
          49                 : #include "nsIDOMDragEvent.h"
          50                 : #include "nsISelection.h"
          51                 : #include "nsCRT.h"
          52                 : #include "nsServiceManagerUtils.h"
          53                 :
          54                 : #include "nsIDOMRange.h"
          55                 : #include "nsIDOMDOMStringList.h"
          56                 : #include "nsIDocumentEncoder.h"
          57                 : #include "nsISupportsPrimitives.h"
          58                 :
          59                 : // Drag & Drop, Clipboard
          60                 : #include "nsIClipboard.h"
          61                 : #include "nsITransferable.h"
          62                 : #include "nsIDragService.h"
          63                 : #include "nsIDOMUIEvent.h"
          64                 : #include "nsCopySupport.h"
          65                 : #include "nsITransferable.h"
          66                 :
          67                 : // Misc
          68                 : #include "nsEditorUtils.h"
          69                 : #include "nsContentCID.h"
          70                 : #include "nsISelectionPrivate.h"
          71                 : #include "nsFrameSelection.h"
          72                 : #include "nsEventDispatcher.h"
          73                 : #include "nsContentUtils.h"
          74                 :
          75                 : using namespace mozilla;
          76                 :
          77               0 : NS_IMETHODIMP nsPlaintextEditor::PrepareTransferable(nsITransferable **transferable)
          78                 : {
          79                 :   // Create generic Transferable for getting the data
          80               0 :   nsresult rv = CallCreateInstance("@mozilla.org/widget/transferable;1", transferable);
          81               0 :   NS_ENSURE_SUCCESS(rv, rv);
          82                 :
          83                 :   // Get the nsITransferable interface for getting the data from the clipboard
          84               0 :   if (transferable) {
          85               0 :     (*transferable)->AddDataFlavor(kUnicodeMime);
          86               0 :     (*transferable)->AddDataFlavor(kMozTextInternal);
          87                 :   };
          88               0 :   return NS_OK;
          89                 : }
          90                 :
          91               0 : nsresult nsPlaintextEditor::InsertTextAt(const nsAString &aStringToInsert,
          92                 :                                          nsIDOMNode *aDestinationNode,
          93                 :                                          PRInt32 aDestOffset,
          94                 :                                          bool aDoDeleteSelection)
          95                 : {
          96               0 :   if (aDestinationNode)
          97                 :   {
          98                 :     nsresult res;
          99               0 :     nsCOMPtr<nsISelection>selection;
         100               0 :     res = GetSelection(getter_AddRefs(selection));
         101               0 :     NS_ENSURE_SUCCESS(res, res);
         102                 :
         103               0 :     nsCOMPtr<nsIDOMNode> targetNode = aDestinationNode;
         104               0 :     PRInt32 targetOffset = aDestOffset;
         105                 :
         106               0 :     if (aDoDeleteSelection)
         107                 :     {
         108                 :       // Use an auto tracker so that our drop point is correctly
         109                 :       // positioned after the delete.
         110               0 :       nsAutoTrackDOMPoint tracker(mRangeUpdater, &targetNode, &targetOffset);
         111               0 :       res = DeleteSelection(eNone);
         112               0 :       NS_ENSURE_SUCCESS(res, res);
         113                 :     }
         114                 :
         115               0 :     res = selection->Collapse(targetNode, targetOffset);
         116               0 :     NS_ENSURE_SUCCESS(res, res);
         117                 :   }
         118                 :
         119               0 :   return InsertText(aStringToInsert);
         120                 : }
         121                 :
         122               0 : NS_IMETHODIMP nsPlaintextEditor::InsertTextFromTransferable(nsITransferable *aTransferable,
         123                 :                                                             nsIDOMNode *aDestinationNode,
         124                 :                                                             PRInt32 aDestOffset,
         125                 :                                                             bool aDoDeleteSelection)
         126                 : {
         127               0 :   FireTrustedInputEvent trusted(this);
         128                 :
         129               0 :   nsresult rv = NS_OK;
         130               0 :   char* bestFlavor = nsnull;
         131               0 :   nsCOMPtr<nsISupports> genericDataObj;
         132               0 :   PRUint32 len = 0;
         133               0 :   if (NS_SUCCEEDED(aTransferable->GetAnyTransferData(&bestFlavor, getter_AddRefs(genericDataObj), &len))
         134               0 :       && bestFlavor && (0 == nsCRT::strcmp(bestFlavor, kUnicodeMime) ||
         135               0 :                         0 == nsCRT::strcmp(bestFlavor, kMozTextInternal)))
         136                 :   {
         137               0 :     nsAutoTxnsConserveSelection dontSpazMySelection(this);
         138               0 :     nsCOMPtr<nsISupportsString> textDataObj ( do_QueryInterface(genericDataObj) );
         139               0 :     if (textDataObj && len > 0)
         140                 :     {
         141               0 :       nsAutoString stuffToPaste;
         142               0 :       textDataObj->GetData(stuffToPaste);
         143               0 :       NS_ASSERTION(stuffToPaste.Length() <= (len/2), "Invalid length!");
         144                 :
         145                 :       // Sanitize possible carriage returns in the string to be inserted
         146               0 :       nsContentUtils::PlatformToDOMLineBreaks(stuffToPaste);
         147                 :
         148               0 :       nsAutoEditBatch beginBatching(this);
         149               0 :       rv = InsertTextAt(stuffToPaste, aDestinationNode, aDestOffset, aDoDeleteSelection);
         150                 :     }
         151                 :   }
         152               0 :   NS_Free(bestFlavor);
         153                 :
         154                 :   // Try to scroll the selection into view if the paste/drop succeeded
         155                 :
         156               0 :   if (NS_SUCCEEDED(rv))
         157               0 :     ScrollSelectionIntoView(false);
         158                 :
         159               0 :   return rv;
         160                 : }
         161                 :
         162               0 : nsresult nsPlaintextEditor::InsertFromDataTransfer(nsIDOMDataTransfer *aDataTransfer,
         163                 :                                                    PRInt32 aIndex,
         164                 :                                                    nsIDOMDocument *aSourceDoc,
         165                 :                                                    nsIDOMNode *aDestinationNode,
         166                 :                                                    PRInt32 aDestOffset,
         167                 :                                                    bool aDoDeleteSelection)
         168                 : {
         169               0 :   nsCOMPtr<nsIVariant> data;
         170               0 :   aDataTransfer->MozGetDataAt(NS_LITERAL_STRING("text/plain"), aIndex,
         171               0 :                               getter_AddRefs(data));
         172               0 :   if (data) {
         173               0 :     nsAutoString insertText;
         174               0 :     data->GetAsAString(insertText);
         175               0 :     nsContentUtils::PlatformToDOMLineBreaks(insertText);
         176                 :
         177               0 :     nsAutoEditBatch beginBatching(this);
         178               0 :     return InsertTextAt(insertText, aDestinationNode, aDestOffset, aDoDeleteSelection);
         179                 :   }
         180                 :
         181               0 :   return NS_OK;
         182                 : }
         183                 :
         184               0 : nsresult nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
         185                 : {
         186               0 :   ForceCompositionEnd();
         187                 :
         188               0 :   nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aDropEvent));
         189               0 :   NS_ENSURE_TRUE(dragEvent, NS_ERROR_FAILURE);
         190                 :
         191               0 :   nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
         192               0 :   nsresult rv = dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
         193               0 :   NS_ENSURE_SUCCESS(rv, rv);
         194                 :
         195                 :   // Current doc is destination
         196               0 :   nsCOMPtr<nsIDOMDocument> destdomdoc;
         197               0 :   rv = GetDocument(getter_AddRefs(destdomdoc));
         198               0 :   NS_ENSURE_SUCCESS(rv, rv);
         199                 :
         200               0 :   PRUint32 numItems = 0;
         201               0 :   rv = dataTransfer->GetMozItemCount(&numItems);
         202               0 :   NS_ENSURE_SUCCESS(rv, rv);
         203               0 :   if (numItems < 1) return NS_ERROR_FAILURE;  // nothing to drop?
         204                 :
         205                 :   // Combine any deletion and drop insertion into one transaction
         206               0 :   nsAutoEditBatch beginBatching(this);
         207                 :
         208               0 :   bool deleteSelection = false;
         209                 :
         210                 :   // We have to figure out whether to delete and relocate caret only once
         211                 :   // Parent and offset are under the mouse cursor
         212               0 :   nsCOMPtr<nsIDOMUIEvent> uiEvent = do_QueryInterface(aDropEvent);
         213               0 :   NS_ENSURE_TRUE(uiEvent, NS_ERROR_FAILURE);
         214                 :
         215               0 :   nsCOMPtr<nsIDOMNode> newSelectionParent;
         216               0 :   rv = uiEvent->GetRangeParent(getter_AddRefs(newSelectionParent));
         217               0 :   NS_ENSURE_SUCCESS(rv, rv);
         218               0 :   NS_ENSURE_TRUE(newSelectionParent, NS_ERROR_FAILURE);
         219                 :
         220                 :   PRInt32 newSelectionOffset;
         221               0 :   rv = uiEvent->GetRangeOffset(&newSelectionOffset);
         222               0 :   NS_ENSURE_SUCCESS(rv, rv);
         223                 :
         224               0 :   nsCOMPtr<nsISelection> selection;
         225               0 :   rv = GetSelection(getter_AddRefs(selection));
         226               0 :   NS_ENSURE_SUCCESS(rv, rv);
         227               0 :   NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
         228                 :
         229                 :   bool isCollapsed;
         230               0 :   rv = selection->GetIsCollapsed(&isCollapsed);
         231               0 :   NS_ENSURE_SUCCESS(rv, rv);
         232                 :
         233               0 :   nsCOMPtr<nsIDOMNode> sourceNode;
         234               0 :   dataTransfer->GetMozSourceNode(getter_AddRefs(sourceNode));
         235                 :
         236               0 :   nsCOMPtr<nsIDOMDocument> srcdomdoc;
         237               0 :   if (sourceNode) {
         238               0 :     sourceNode->GetOwnerDocument(getter_AddRefs(srcdomdoc));
         239               0 :     NS_ENSURE_TRUE(sourceNode, NS_ERROR_FAILURE);
         240                 :   }
         241                 :
         242                 :   // Only the nsHTMLEditor::FindUserSelectAllNode returns a node.
         243               0 :   nsCOMPtr<nsIDOMNode> userSelectNode = FindUserSelectAllNode(newSelectionParent);
         244               0 :   if (userSelectNode)
         245                 :   {
         246                 :     // The drop is happening over a "-moz-user-select: all"
         247                 :     // subtree so make sure the content we insert goes before
         248                 :     // the root of the subtree.
         249                 :     //
         250                 :     // XXX: Note that inserting before the subtree matches the
         251                 :     //      current behavior when dropping on top of an image.
         252                 :     //      The decision for dropping before or after the
         253                 :     //      subtree should really be done based on coordinates.
         254                 :
         255                 :     rv = GetNodeLocation(userSelectNode, address_of(newSelectionParent),
         256               0 :                          &newSelectionOffset);
         257                 :
         258               0 :     NS_ENSURE_SUCCESS(rv, rv);
         259               0 :     NS_ENSURE_TRUE(newSelectionParent, NS_ERROR_FAILURE);
         260                 :   }
         261                 :
         262                 :   // Check if mouse is in the selection
         263                 :   // if so, jump through some hoops to determine if mouse is over selection (bail)
         264                 :   // and whether user wants to copy selection or delete it
         265               0 :   if (!isCollapsed)
         266                 :   {
         267                 :     // We never have to delete if selection is already collapsed
         268               0 :     bool cursorIsInSelection = false;
         269                 :
         270                 :     PRInt32 rangeCount;
         271               0 :     rv = selection->GetRangeCount(&rangeCount);
         272               0 :     NS_ENSURE_SUCCESS(rv, rv);
         273                 :
         274               0 :     for (PRInt32 j = 0; j < rangeCount; j++)
         275                 :     {
         276               0 :       nsCOMPtr<nsIDOMRange> range;
         277               0 :       rv = selection->GetRangeAt(j, getter_AddRefs(range));
         278               0 :       if (NS_FAILED(rv) || !range)
         279               0 :         continue;  // don't bail yet, iterate through them all
         280                 :
         281               0 :       rv = range->IsPointInRange(newSelectionParent, newSelectionOffset, &cursorIsInSelection);
         282               0 :       if (cursorIsInSelection)
         283                 :         break;
         284                 :     }
         285                 :
         286               0 :     if (cursorIsInSelection)
         287                 :     {
         288                 :       // Dragging within same doc can't drop on itself -- leave!
         289               0 :       if (srcdomdoc == destdomdoc)
         290               0 :         return NS_OK;
         291                 :
         292                 :       // Dragging from another window onto a selection
         293                 :       // XXX Decision made to NOT do this,
         294                 :       //     note that 4.x does replace if dropped on
         295                 :       //deleteSelection = true;
         296                 :     }
         297                 :     else
         298                 :     {
         299                 :       // We are NOT over the selection
         300               0 :       if (srcdomdoc == destdomdoc)
         301                 :       {
         302                 :         // Within the same doc: delete if user doesn't want to copy
         303                 :         PRUint32 dropEffect;
         304               0 :         dataTransfer->GetDropEffectInt(&dropEffect);
         305               0 :         deleteSelection = !(dropEffect & nsIDragService::DRAGDROP_ACTION_COPY);
         306                 :       }
         307                 :       else
         308                 :       {
         309                 :         // Different source doc: Don't delete
         310               0 :         deleteSelection = false;
         311                 :       }
         312                 :     }
         313                 :   }
         314                 :
         315               0 :   if (IsPlaintextEditor()) {
         316               0 :     nsCOMPtr<nsIContent> content = do_QueryInterface(newSelectionParent);
         317               0 :     while (content) {
         318               0 :       nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(content));
         319               0 :       if (formControl && !formControl->AllowDrop()) {
         320                 :         // Don't allow dropping into a form control that doesn't allow being
         321                 :         // dropped into.
         322               0 :         return NS_OK;
         323                 :       }
         324               0 :       content = content->GetParent();
         325                 :     }
         326                 :   }
         327                 :
         328               0 :   for (PRUint32 i = 0; i < numItems; ++i) {
         329                 :     InsertFromDataTransfer(dataTransfer, i, srcdomdoc, newSelectionParent,
         330               0 :                            newSelectionOffset, deleteSelection);
         331                 :   }
         332                 :
         333               0 :   if (NS_SUCCEEDED(rv))
         334               0 :     ScrollSelectionIntoView(false);
         335                 :
         336               0 :   return rv;
         337                 : }
         338                 :
         339               0 : NS_IMETHODIMP nsPlaintextEditor::Paste(PRInt32 aSelectionType)
         340                 : {
         341               0 :   if (!FireClipboardEvent(NS_PASTE))
         342               0 :     return NS_OK;
         343                 :
         344                 :   // Get Clipboard Service
         345                 :   nsresult rv;
         346               0 :   nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
         347               0 :   if ( NS_FAILED(rv) )
         348               0 :     return rv;
         349                 :
         350                 :   // Get the nsITransferable interface for getting the data from the clipboard
         351               0 :   nsCOMPtr<nsITransferable> trans;
         352               0 :   rv = PrepareTransferable(getter_AddRefs(trans));
         353               0 :   if (NS_SUCCEEDED(rv) && trans)
         354                 :   {
         355                 :     // Get the Data from the clipboard
         356               0 :     if (NS_SUCCEEDED(clipboard->GetData(trans, aSelectionType)) && IsModifiable())
         357                 :     {
         358                 :       // handle transferable hooks
         359               0 :       nsCOMPtr<nsIDOMDocument> domdoc;
         360               0 :       GetDocument(getter_AddRefs(domdoc));
         361               0 :       if (!nsEditorHookUtils::DoInsertionHook(domdoc, nsnull, trans))
         362               0 :         return NS_OK;
         363                 :
         364               0 :       rv = InsertTextFromTransferable(trans, nsnull, nsnull, true);
         365                 :     }
         366                 :   }
         367                 :
         368               0 :   return rv;
         369                 : }
         370                 :
         371               0 : NS_IMETHODIMP nsPlaintextEditor::PasteTransferable(nsITransferable *aTransferable)
         372                 : {
         373               0 :   if (!FireClipboardEvent(NS_PASTE))
         374               0 :     return NS_OK;
         375                 :
         376               0 :   if (!IsModifiable())
         377               0 :     return NS_OK;
         378                 :
         379                 :   // handle transferable hooks
         380               0 :   nsCOMPtr<nsIDOMDocument> domdoc;
         381               0 :   GetDocument(getter_AddRefs(domdoc));
         382               0 :   if (!nsEditorHookUtils::DoInsertionHook(domdoc, nsnull, aTransferable))
         383               0 :     return NS_OK;
         384                 :
         385               0 :   return InsertTextFromTransferable(aTransferable, nsnull, nsnull, true);
         386                 : }
         387                 :
         388               0 : NS_IMETHODIMP nsPlaintextEditor::CanPaste(PRInt32 aSelectionType, bool *aCanPaste)
         389                 : {
         390               0 :   NS_ENSURE_ARG_POINTER(aCanPaste);
         391               0 :   *aCanPaste = false;
         392                 :
         393                 :   // can't paste if readonly
         394               0 :   if (!IsModifiable())
         395               0 :     return NS_OK;
         396                 :
         397                 :   nsresult rv;
         398               0 :   nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
         399               0 :   NS_ENSURE_SUCCESS(rv, rv);
         400                 :
         401                 :   // the flavors that we can deal with
         402               0 :   const char* textEditorFlavors[] = { kUnicodeMime };
         403                 :
         404                 :   bool haveFlavors;
         405               0 :   rv = clipboard->HasDataMatchingFlavors(textEditorFlavors,
         406                 :                                          ArrayLength(textEditorFlavors),
         407               0 :                                          aSelectionType, &haveFlavors);
         408               0 :   NS_ENSURE_SUCCESS(rv, rv);
         409                 :
         410               0 :   *aCanPaste = haveFlavors;
         411               0 :   return NS_OK;
         412                 : }
         413                 :
         414                 :
         415               0 : NS_IMETHODIMP nsPlaintextEditor::CanPasteTransferable(nsITransferable *aTransferable, bool *aCanPaste)
         416                 : {
         417               0 :   NS_ENSURE_ARG_POINTER(aCanPaste);
         418                 :
         419                 :   // can't paste if readonly
         420               0 :   if (!IsModifiable()) {
         421               0 :     *aCanPaste = false;
         422               0 :     return NS_OK;
         423                 :   }
         424                 :
         425                 :   // If |aTransferable| is null, assume that a paste will succeed.
         426               0 :   if (!aTransferable) {
         427               0 :     *aCanPaste = true;
         428               0 :     return NS_OK;
         429                 :   }
         430                 :
         431               0 :   nsCOMPtr<nsISupports> data;
         432                 :   PRUint32 dataLen;
         433                 :   nsresult rv = aTransferable->GetTransferData(kUnicodeMime,
         434               0 :                                                getter_AddRefs(data),
         435               0 :                                                &dataLen);
         436               0 :   if (NS_SUCCEEDED(rv) && data)
         437               0 :     *aCanPaste = true;
         438                 :   else
         439               0 :     *aCanPaste = false;
         440                 :
         441               0 :   return NS_OK;
         442                 : }

Generated by: LCOV version 1.7