PRUnichar* text = nsnull;
nsAutoString text;
NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent){  ForceCompositionEnd();    nsresult rv;  nsCOMPtr<nsIDragService> dragService =            do_GetService("@mozilla.org/widget/dragservice;1", &rv);  if (NS_FAILED(rv)) return rv;  nsCOMPtr<nsIDragSession> dragSession;  dragService->GetCurrentSession(getter_AddRefs(dragSession));   if (!dragSession) return NS_OK;  // Get the nsITransferable interface for getting the data from the drop  nsCOMPtr<nsITransferable> trans;  rv = PrepareTransferable(getter_AddRefs(trans));  if (NS_FAILED(rv)) return rv;  if (!trans) return NS_OK;  // NS_ERROR_FAILURE; SHOULD WE FAIL?  PRUint32 numItems = 0;   rv = dragSession->GetNumDropItems(&numItems);  if (NS_FAILED(rv)) return rv;  // Combine any deletion and drop insertion into one transaction  nsAutoEditBatch beginBatching(this);  PRUint32 i;   PRBool doPlaceCaret = PR_TRUE;  for (i = 0; i < numItems; ++i)  {    rv = dragSession->GetData(trans, i);    if (NS_FAILED(rv)) return rv;    if (!trans) return NS_OK; // NS_ERROR_FAILURE; Should we fail?    // get additional html copy hints, if present    nsAutoString contextStr, infoStr;    nsCOMPtr<nsISupports> contextDataObj, infoDataObj;    PRUint32 contextLen, infoLen;    nsCOMPtr<nsISupportsWString> textDataObj;        nsCOMPtr<nsITransferable> contextTrans = do_CreateInstance(kCTransferableCID);    NS_ENSURE_TRUE(contextTrans, NS_ERROR_NULL_POINTER);    contextTrans->AddDataFlavor(kHTMLContext);    dragSession->GetData(contextTrans, i);    contextTrans->GetTransferData(kHTMLContext, getter_AddRefs(contextDataObj), &contextLen);    nsCOMPtr<nsITransferable> infoTrans = do_CreateInstance(kCTransferableCID);    NS_ENSURE_TRUE(infoTrans, NS_ERROR_NULL_POINTER);    infoTrans->AddDataFlavor(kHTMLInfo);    dragSession->GetData(infoTrans, i);    infoTrans->GetTransferData(kHTMLInfo, getter_AddRefs(infoDataObj), &infoLen);        if (contextDataObj)    {      PRUnichar* text = nsnull;      textDataObj = do_QueryInterface(contextDataObj);      textDataObj->ToString ( &text );      contextStr.Assign ( text, contextLen / 2 );      if (text)        nsMemory::Free(text);    }        if (infoDataObj)    {      PRUnichar* text = nsnull;      textDataObj = do_QueryInterface(infoDataObj);      textDataObj->ToString ( &text );      infoStr.Assign ( text, infoLen / 2 );      if (text)        nsMemory::Free(text);    }    if ( doPlaceCaret )    {      // check if the user pressed the key to force a copy rather than a move      // if we run into problems here, we'll just assume the user doesn't want a copy      PRBool userWantsCopy = PR_FALSE;      nsCOMPtr<nsIDOMNSUIEvent> nsuiEvent (do_QueryInterface(aDropEvent));      if (!nsuiEvent) return NS_ERROR_FAILURE;      nsCOMPtr<nsIDOMMouseEvent> mouseEvent ( do_QueryInterface(aDropEvent) );      if (mouseEvent)#ifdef XP_MAC        mouseEvent->GetAltKey(&userWantsCopy);#else        mouseEvent->GetCtrlKey(&userWantsCopy);#endif      // Source doc is null if source is *not* the current editor document      nsCOMPtr<nsIDOMDocument> srcdomdoc;      rv = dragSession->GetSourceDocument(getter_AddRefs(srcdomdoc));      if (NS_FAILED(rv)) return rv;      // Current doc is destination      nsCOMPtr<nsIDOMDocument>destdomdoc;       rv = GetDocument(getter_AddRefs(destdomdoc));       if (NS_FAILED(rv)) return rv;      nsCOMPtr<nsISelection> selection;      rv = GetSelection(getter_AddRefs(selection));      if (NS_FAILED(rv)) return rv;      if (!selection) return NS_ERROR_FAILURE;      PRBool isCollapsed;      rv = selection->GetIsCollapsed(&isCollapsed);      if (NS_FAILED(rv)) return rv;            // Parent and offset under the mouse cursor      nsCOMPtr<nsIDOMNode> newSelectionParent;      PRInt32 newSelectionOffset = 0;      rv = nsuiEvent->GetRangeParent(getter_AddRefs(newSelectionParent));      if (NS_FAILED(rv)) return rv;      if (!newSelectionParent) return NS_ERROR_FAILURE;      rv = nsuiEvent->GetRangeOffset(&newSelectionOffset);      if (NS_FAILED(rv)) return rv;      /* Creating a range to store insert position because when         we delete the selection, range gravity will make sure the insertion         point is in the correct place */      nsCOMPtr<nsIDOMRange> destinationRange;      rv = CreateRange(newSelectionParent, newSelectionOffset,newSelectionParent, newSelectionOffset, getter_AddRefs(destinationRange));      if (NS_FAILED(rv))        return rv;      if(!destinationRange)        return NS_ERROR_FAILURE;      // We never have to delete if selection is already collapsed      PRBool deleteSelection = PR_FALSE;      PRBool cursorIsInSelection = PR_FALSE;      // Check if mouse is in the selection      if (!isCollapsed)      {        PRInt32 rangeCount;        rv = selection->GetRangeCount(&rangeCount);        if (NS_FAILED(rv))           return rv;        for (PRInt32 j = 0; j < rangeCount; j++)        {          nsCOMPtr<nsIDOMRange> range;          rv = selection->GetRangeAt(j, getter_AddRefs(range));          if (NS_FAILED(rv) || !range)             continue;//dont bail yet, iterate through them all          nsCOMPtr<nsIDOMNSRange> nsrange(do_QueryInterface(range));          if (NS_FAILED(rv) || !nsrange)             continue;//dont bail yet, iterate through them all          rv = nsrange->IsPointInRange(newSelectionParent, newSelectionOffset, &cursorIsInSelection);          if(cursorIsInSelection)            break;        }        if (cursorIsInSelection)        {          // Dragging within same doc can't drop on itself -- leave!          // (We shouldn't get here - drag event shouldn't have started if over selection)          if (srcdomdoc == destdomdoc)            return NS_OK;                    // Dragging from another window onto a selection          // XXX Decision made to NOT do this,          //     note that 4.x does replace if dropped on          //deleteSelection = PR_TRUE;        }        else         {          // We are NOT over the selection          if (srcdomdoc == destdomdoc)          {            // Within the same doc: delete if user doesn't want to copy            deleteSelection = !userWantsCopy;          }          else          {            // Different source doc: Don't delete            deleteSelection = PR_FALSE;          }        }      }      if (deleteSelection)      {        rv = DeleteSelection(eNone);        if (NS_FAILED(rv)) return rv;      }      // If we deleted the selection because we dropped from another doc,      //  then we don't have to relocate the caret (insert at the deletion point)      if (!(deleteSelection && srcdomdoc != destdomdoc))      {        // Move the selection to the point under the mouse cursor        rv = destinationRange->GetStartContainer(getter_AddRefs(newSelectionParent));        if (NS_FAILED(rv))          return rv;        if(!newSelectionParent)          return NS_ERROR_FAILURE;               rv = destinationRange->GetStartOffset(&newSelectionOffset);        if (NS_FAILED(rv))          return rv;        selection->Collapse(newSelectionParent, newSelectionOffset);      }            // We have to figure out whether to delete and relocate caret only once      doPlaceCaret = PR_FALSE;    }        rv = InsertFromTransferable(trans, contextStr, infoStr);  }  return rv;}