From 06f0642f0be5b5ac79196fa922b4a7908fbbab4f Mon Sep 17 00:00:00 2001 From: "cmanske%netscape.com" Date: Tue, 5 Sep 2000 23:26:48 +0000 Subject: [PATCH] Composer bugs: Drag and drop problems (47399, r=anthonyd), workaround for bad dragNdrop event (50703, r=nisheeth) git-svn-id: svn://10.0.0.236/trunk@78187 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/editor/base/nsComposerCommands.cpp | 7 +- .../editor/base/nsEditorEventListeners.cpp | 85 ++++--- .../base/nsEditorShellMouseListener.cpp | 219 +++++++++++------- mozilla/editor/base/nsHTMLEditor.cpp | 204 +++++++++++----- mozilla/editor/base/nsHTMLEditor.h | 4 + .../composer/src/nsComposerCommands.cpp | 7 +- .../src/nsEditorShellMouseListener.cpp | 219 +++++++++++------- .../editor/libeditor/html/nsHTMLEditor.cpp | 204 +++++++++++----- mozilla/editor/libeditor/html/nsHTMLEditor.h | 4 + .../libeditor/text/nsEditorEventListeners.cpp | 85 ++++--- mozilla/editor/public/nsIHTMLEditor.h | 23 +- .../editor/ui/dialogs/content/EdColorProps.js | 2 - 12 files changed, 691 insertions(+), 372 deletions(-) diff --git a/mozilla/editor/base/nsComposerCommands.cpp b/mozilla/editor/base/nsComposerCommands.cpp index 1272bf0bdf7..aae1aab7b36 100644 --- a/mozilla/editor/base/nsComposerCommands.cpp +++ b/mozilla/editor/base/nsComposerCommands.cpp @@ -474,9 +474,12 @@ nsRemoveListCommand::IsCommandEnabled(const PRUnichar *aCommand, nsISupports * r PRUnichar *tagStr; nsresult rv = editorShell->GetListState(&bMixed, &tagStr); if (NS_FAILED(rv)) return rv; - - *outCmdEnabled = (tagStr && *tagStr != nsnull); + if (bMixed) + *outCmdEnabled = PR_TRUE; + else + *outCmdEnabled = (tagStr && *tagStr); + if (tagStr) nsCRT::free(tagStr); } diff --git a/mozilla/editor/base/nsEditorEventListeners.cpp b/mozilla/editor/base/nsEditorEventListeners.cpp index 5679cbbb66e..7c6076ac5c7 100644 --- a/mozilla/editor/base/nsEditorEventListeners.cpp +++ b/mozilla/editor/base/nsEditorEventListeners.cpp @@ -682,11 +682,11 @@ nsTextEditorDragListener::DragDrop(nsIDOMEvent* aMouseEvent) { nsresult rv; NS_WITH_SERVICE(nsIDragService, dragService, "component://netscape/widget/dragservice", &rv); - if (NS_FAILED(rv)) return rv; + if (NS_FAILED(rv)) return rv; nsCOMPtr dragSession(do_QueryInterface(dragService)); if (dragSession) - { + { PRBool flavorSupported = PR_FALSE; dragSession->IsDataFlavorSupported(kUnicodeMime, &flavorSupported); if ( !flavorSupported ) @@ -696,54 +696,73 @@ nsTextEditorDragListener::DragDrop(nsIDOMEvent* aMouseEvent) if ( !flavorSupported ) dragSession->IsDataFlavorSupported(kJPEGImageMime, &flavorSupported); if (! flavorSupported ) - return NS_OK; - } + return NS_OK; + } + nsCOMPtr nsuiEvent (do_QueryInterface(aMouseEvent)); + if (!nsuiEvent) return NS_OK; //some day we want to use another way to stop this from bubbling. aMouseEvent->PreventBubble(); aMouseEvent->PreventDefault(); /* for bug 47399, when dropping a drag session, if you are over your original - selection, nothing should happen. */ - nsCOMPtr tempSelection; - rv = mEditor->GetSelection(getter_AddRefs(tempSelection)); - if (NS_FAILED(rv) || !tempSelection) + selection, nothing should happen. + cmanske: But do this only if drag source is not the same as target (current) document! + */ + nsCOMPtr selection; + rv = mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(rv) || !selection) return rv?rv:NS_ERROR_FAILURE; - PRInt32 rangeCount; - rv = tempSelection->GetRangeCount(&rangeCount); - if (NS_FAILED(rv)) - return rv?rv:NS_ERROR_FAILURE; + nsCOMPtr editor = do_QueryInterface(htmlEditor); + nsCOMPtr domdoc; + rv = editor->GetDocument(getter_AddRefs(domdoc)); + if (NS_FAILED(rv)) return rv; - for(int i = 0; i < rangeCount; i++) + nsCOMPtr sourceDoc; + rv = dragSession->GetSourceDocument(getter_AddRefs(sourceDoc)); + if (NS_FAILED(rv)) return rv; + if (domdoc == sourceDoc) { - nsCOMPtr range; + PRBool isCollapsed; + rv = selection->GetIsCollapsed(&isCollapsed); + if (NS_FAILED(rv)) return rv; + + // Don't bother if collapsed - can always drop + if (!isCollapsed) + { + nsCOMPtr parent; + rv = nsuiEvent->GetRangeParent(getter_AddRefs(parent)); + if (NS_FAILED(rv)) return rv; + if (!parent) return NS_ERROR_FAILURE; - rv = tempSelection->GetRangeAt(i, getter_AddRefs(range)); - if (NS_FAILED(rv) || !range) - continue;//dont bail yet, iterate through them all + PRInt32 offset = 0; + rv = nsuiEvent->GetRangeOffset(&offset); + if (NS_FAILED(rv)) return rv; - nsCOMPtr nsrange(do_QueryInterface(range)); - if (NS_FAILED(rv) || !nsrange) - continue;//dont bail yet, iterate through them all + PRInt32 rangeCount; + rv = selection->GetRangeCount(&rangeCount); + if (NS_FAILED(rv)) return rv; - nsCOMPtr nsuiEvent (do_QueryInterface(aMouseEvent)); - if (!nsuiEvent) - continue;//dont bail yet, iterate through them all + for (PRInt32 i = 0; i < rangeCount; i++) + { + nsCOMPtr range; - nsCOMPtr parent; - if (!NS_SUCCEEDED(nsuiEvent->GetRangeParent(getter_AddRefs(parent)))) - continue;//dont bail yet, iterate through them all + rv = selection->GetRangeAt(i, getter_AddRefs(range)); + if (NS_FAILED(rv) || !range) + continue;//dont bail yet, iterate through them all - PRInt32 offset = 0; - if (!NS_SUCCEEDED(nsuiEvent->GetRangeOffset(&offset))) - continue;//dont bail yet, iterate through them all + nsCOMPtr nsrange(do_QueryInterface(range)); + if (NS_FAILED(rv) || !nsrange) + continue;//dont bail yet, iterate through them all - PRBool inrange; - rv = nsrange->IsPointInRange(parent, offset, &inrange); - if(inrange) - return NS_ERROR_FAILURE;//okay, now you can bail, we are over the orginal selection + PRBool inrange; + rv = nsrange->IsPointInRange(parent, offset, &inrange); + if(inrange) + return NS_ERROR_FAILURE;//okay, now you can bail, we are over the orginal selection + } + } } // if we are not over orginal selection, drop that baby! return htmlEditor->InsertFromDrop(aMouseEvent); diff --git a/mozilla/editor/base/nsEditorShellMouseListener.cpp b/mozilla/editor/base/nsEditorShellMouseListener.cpp index 2a9a121325f..673348b40b8 100644 --- a/mozilla/editor/base/nsEditorShellMouseListener.cpp +++ b/mozilla/editor/base/nsEditorShellMouseListener.cpp @@ -31,10 +31,16 @@ #include "nsIDOMCharacterData.h" #include "nsIDOMMouseEvent.h" #include "nsIDOMSelection.h" +#include "nsIDOMRange.h" +#include "nsIDOMNSRange.h" #include "nsIDOMEventTarget.h" +#include "nsIDOMNSUIEvent.h" #include "nsIDOMHTMLTableElement.h" #include "nsIDOMHTMLTableCellElement.h" +#include "nsIEditor.h" +#include "nsIHTMLEditor.h" + /* * nsEditorShellMouseListener implementation */ @@ -160,104 +166,144 @@ nsEditorShellMouseListener::MouseDown(nsIDOMEvent* aMouseEvent) //non-ui event passed in. bad things. return NS_OK; } - - PRUint16 buttonNumber; - nsresult res = mouseEvent->GetButton(&buttonNumber); + // Don't do anything special if not an HTML editor + nsCOMPtr editor; + nsresult res = mEditorShell->GetEditor(getter_AddRefs(editor)); if (NS_FAILED(res)) return res; - PRBool isContextClick; - // Test if special 'table selection' key is pressed when double-clicking - // so we look for an enclosing cell or table - PRBool tableMode = PR_FALSE; - -#ifdef XP_MAC - // Cmd is Mac table-select key - res = mouseEvent->GetMetaKey(&tableMode); - if (NS_FAILED(res)) return res; - - // Ctrl+Click for context menu - res = mouseEvent->GetCtrlKey(&isContextClick); -#else - // Right mouse button for Windows, UNIX - isContextClick = buttonNumber == 3; - res = mouseEvent->GetCtrlKey(&tableMode); -#endif - if (NS_FAILED(res)) return res; - - nsCOMPtr target; - res = aMouseEvent->GetTarget(getter_AddRefs(target)); - if (NS_FAILED(res)) return res; - if (!target) return NS_ERROR_NULL_POINTER; - nsCOMPtr element = do_QueryInterface(target); - - PRInt32 clickCount; - res = mouseEvent->GetDetail(&clickCount); - if (NS_FAILED(res)) return res; - - PRBool NodeIsInSelection = PR_FALSE; - - if (isContextClick || (buttonNumber == 1 && clickCount == 2)) + nsCOMPtr htmlEditor = do_QueryInterface(editor); + if (htmlEditor) { - // Context menu or double click - nsCOMPtr node = do_QueryInterface(target); - if (node) + PRUint16 buttonNumber; + res = mouseEvent->GetButton(&buttonNumber); + if (NS_FAILED(res)) return res; + + PRBool isContextClick; + // Test if special 'table selection' key is pressed when double-clicking + // so we look for an enclosing cell or table + PRBool tableMode = PR_FALSE; + + #ifdef XP_MAC + // Cmd is Mac table-select key + res = mouseEvent->GetMetaKey(&tableMode); + if (NS_FAILED(res)) return res; + + // Ctrl+Click for context menu + res = mouseEvent->GetCtrlKey(&isContextClick); + #else + // Right mouse button for Windows, UNIX + isContextClick = buttonNumber == 3; + res = mouseEvent->GetCtrlKey(&tableMode); + #endif + if (NS_FAILED(res)) return res; + + nsCOMPtr target; + res = aMouseEvent->GetTarget(getter_AddRefs(target)); + if (NS_FAILED(res)) return res; + if (!target) return NS_ERROR_NULL_POINTER; + nsCOMPtr element = do_QueryInterface(target); + + PRInt32 clickCount; + res = mouseEvent->GetDetail(&clickCount); + if (NS_FAILED(res)) return res; + + nsCOMPtr selection; + mEditorShell->GetEditorSelection(getter_AddRefs(selection)); + if (!selection) return NS_OK; + + nsCOMPtr parent; + PRInt32 offset = 0; + + // Get location of mouse within target node + nsCOMPtr uiEvent = do_QueryInterface(aMouseEvent); + if (!uiEvent) return NS_ERROR_FAILURE; + + res = uiEvent->GetRangeParent(getter_AddRefs(parent)); + if (NS_FAILED(res)) return res; + if (!parent) return NS_ERROR_FAILURE; + + res = uiEvent->GetRangeOffset(&offset); + if (NS_FAILED(res)) return res; + + // Detect if mouse point is withing current selection + PRBool NodeIsInSelection = PR_FALSE; + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + + if (!isCollapsed) { - nsCOMPtr selection; - mEditorShell->GetEditorSelection(getter_AddRefs(selection)); - if (selection) + PRInt32 rangeCount; + res = selection->GetRangeCount(&rangeCount); + if (NS_FAILED(res)) return res; + + for (PRInt32 i = 0; i < rangeCount; i++) { - res = selection->ContainsNode(node, PR_TRUE, &NodeIsInSelection); - // Kludge: We really want to reposition the caret exactly as done for - // left mouse button, but we never reach the frame's HandlePress method. - // Thus for text nodes, the best we can do is reposition to the start of the node, - // but only if not already selected, of course - if (!NodeIsInSelection) - selection->Collapse(node, 0); + nsCOMPtr range; + + res = selection->GetRangeAt(i, getter_AddRefs(range)); + if (NS_FAILED(res) || !range) + continue;//dont bail yet, iterate through them all + + nsCOMPtr nsrange(do_QueryInterface(range)); + if (NS_FAILED(res) || !nsrange) + continue;//dont bail yet, iterate through them all + + res = nsrange->IsPointInRange(parent, offset, &NodeIsInSelection); } - - // Get enclosing link - nsCOMPtr linkElement; - res = mEditorShell->GetElementOrParentByTagName(NS_LITERAL_STRING("href"), node, getter_AddRefs(linkElement)); - if (NS_FAILED(res)) return res; - if (linkElement) - element = linkElement; } - } - if (isContextClick) - { - // Set selection to node clicked on if NOT within an existing selection - if (element && !NodeIsInSelection) - mEditorShell->SelectElement(element); - // Always fall through to do other actions, such as context menu - } - else if (buttonNumber == 1) - { -#ifdef DEBUG_cmanske -// printf("nsEditorShellMouseListener::MouseDown: clickCount=%d\n",clickCount); -#endif - - if (tableMode && clickCount == 2) + if (isContextClick || (buttonNumber == 1 && clickCount == 2)) { - if (!GetParentCell(aMouseEvent, getter_AddRefs(element))) - GetParentTable(aMouseEvent, getter_AddRefs(element)); + // Context menu or double click + nsCOMPtr node = do_QueryInterface(target); + if (node && !NodeIsInSelection) + { + selection->Collapse(parent, offset); + + // Get enclosing link + nsCOMPtr linkElement; + res = mEditorShell->GetElementOrParentByTagName(NS_LITERAL_STRING("href"), node, getter_AddRefs(linkElement)); + if (NS_FAILED(res)) return res; + if (linkElement) + element = linkElement; + } } - // No table or cell -- look for other element (ignore text nodes) - if (element) + + if (isContextClick) { - PRInt32 x,y; - res = mouseEvent->GetClientX(&x); - if (NS_FAILED(res)) return res; + // Set selection to node clicked on if NOT within an existing selection + if (element && !NodeIsInSelection) + mEditorShell->SelectElement(element); + // Always fall through to do other actions, such as context menu + } + else if (buttonNumber == 1) + { + if (tableMode && clickCount == 2) + { + if (!GetParentCell(aMouseEvent, getter_AddRefs(element))) + GetParentTable(aMouseEvent, getter_AddRefs(element)); + } + // No table or cell -- look for other element (ignore text nodes) + if (element) + { + PRInt32 x,y; + res = mouseEvent->GetClientX(&x); + if (NS_FAILED(res)) return res; - res = mouseEvent->GetClientY(&y); - if (NS_FAILED(res)) return res; + res = mouseEvent->GetClientY(&y); + if (NS_FAILED(res)) return res; - // Let editor decide what to do with this - PRBool handled = PR_FALSE; - mEditorShell->HandleMouseClickOnElement(element, clickCount, x, y, &handled); + // KLUDGE to work around bug 50703: Prevent drag/drop events until we are done + if (clickCount == 2) + htmlEditor->IgnoreSpuriousDragEvent(PR_TRUE); - if (handled) - mouseEvent->PreventDefault(); + // Let editor decide what to do with this + PRBool handled = PR_FALSE; + mEditorShell->HandleMouseClickOnElement(element, clickCount, x, y, &handled); + + if (handled) + mouseEvent->PreventDefault(); + } } } @@ -267,10 +313,7 @@ nsEditorShellMouseListener::MouseDown(nsIDOMEvent* aMouseEvent) nsresult nsEditorShellMouseListener::MouseUp(nsIDOMEvent* aMouseEvent) { -#ifdef DEBUG_cmanske -printf("* nsEditorShellMouseListener::MouseUp message\n"); -#endif - return NS_OK; // didn't handle event + return NS_OK; } nsresult diff --git a/mozilla/editor/base/nsHTMLEditor.cpp b/mozilla/editor/base/nsHTMLEditor.cpp index 29f0d3f7064..268f34855e5 100644 --- a/mozilla/editor/base/nsHTMLEditor.cpp +++ b/mozilla/editor/base/nsHTMLEditor.cpp @@ -239,6 +239,7 @@ nsHTMLEditor::nsHTMLEditor() , mIsComposing(PR_FALSE) , mMaxTextLength(-1) , mSelectedCellIndex(0) +, mIgnoreSpuriousDragEvent(PR_FALSE) { // Done in nsEditor // NS_INIT_REFCNT(); @@ -2620,7 +2621,7 @@ nsHTMLEditor::ReplaceHeadContentsWithHTML(const nsString &aSourceToInsert) res = nsrange->CreateContextualFragment(inputString, getter_AddRefs(docfrag)); - //XXXX BUG: This is not returning the text between ... + //XXXX BUG 50965: This is not returning the text between ... // Special code is needed in JS to handle title anyway, so it really doesn't matter! if (NS_FAILED(res)) @@ -5000,7 +5001,6 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable return rv; } - NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent) { ForceCompositionEnd(); @@ -5011,74 +5011,150 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent) nsCOMPtr dragSession(do_QueryInterface(dragService)); - if (dragSession) + if (!dragSession) return NS_OK; + + // Get the nsITransferable interface for getting the data from the drop + nsCOMPtr 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) { - // Get the nsITransferable interface for getting the data from the drop - nsCOMPtr trans; - rv = PrepareTransferable(getter_AddRefs(trans)); - if (NS_SUCCEEDED(rv) && trans) + rv = dragSession->GetData(trans, i); + if (NS_FAILED(rv)) return rv; + if (!trans) return NS_OK; // NS_ERROR_FAILURE; Should we fail? + + if ( doPlaceCaret ) { - PRUint32 numItems = 0; - if (NS_SUCCEEDED(dragSession->GetNumDropItems(&numItems))) - { - PRUint32 i; - PRBool doPlaceCaret = PR_TRUE; - for (i = 0; i < numItems; ++i) - { - if (NS_SUCCEEDED(dragSession->GetData(trans, i))) - { - 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 mouseEvent ( do_QueryInterface(aDropEvent) ); - if (mouseEvent) + // 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 nsuiEvent (do_QueryInterface(aDropEvent)); + if (!nsuiEvent) return NS_ERROR_FAILURE; + + nsCOMPtr mouseEvent ( do_QueryInterface(aDropEvent) ); + if (mouseEvent) + #ifdef XP_MAC - mouseEvent->GetAltKey(&userWantsCopy); // check modifiers here + mouseEvent->GetAltKey(&userWantsCopy); #else - mouseEvent->GetCtrlKey(&userWantsCopy); // check modifiers here + mouseEvent->GetCtrlKey(&userWantsCopy); #endif - - nsCOMPtr srcdomdoc; - dragSession->GetSourceDocument(getter_AddRefs(srcdomdoc)); - if (srcdomdoc) - { - // do deletion of selection if sourcedocument is current document && appropriate modifier isn't pressed - nsCOMPtrdestdomdoc; - rv = GetDocument(getter_AddRefs(destdomdoc)); - if ( NS_SUCCEEDED(rv) && !userWantsCopy && (srcdomdoc == destdomdoc) ) - { - rv = DeleteSelection(eNone); - if (NS_FAILED(rv)) - return rv; - } - } + // Source doc is null if source is *not* the current editor document + nsCOMPtr srcdomdoc; + rv = dragSession->GetSourceDocument(getter_AddRefs(srcdomdoc)); + if (NS_FAILED(rv)) return rv; - // Set the selection to the point under the mouse cursor: - nsCOMPtr nsuiEvent (do_QueryInterface(aDropEvent)); + // Current doc is destination + nsCOMPtrdestdomdoc; + rv = GetDocument(getter_AddRefs(destdomdoc)); + if (NS_FAILED(rv)) return rv; - if (!nsuiEvent) - return NS_ERROR_NULL_POINTER; - nsCOMPtr parent; - if (!NS_SUCCEEDED(nsuiEvent->GetRangeParent(getter_AddRefs(parent)))) - return NS_ERROR_NULL_POINTER; - PRInt32 offset = 0; - if (!NS_SUCCEEDED(nsuiEvent->GetRangeOffset(&offset))) - return NS_ERROR_NULL_POINTER; + nsCOMPtr selection; + rv = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(rv)) return rv; + if (!selection) return NS_ERROR_FAILURE; - nsCOMPtr selection; - if (NS_SUCCEEDED(GetSelection(getter_AddRefs(selection)))) - (void)selection->Collapse(parent, offset); + PRBool isCollapsed; + rv = selection->GetIsCollapsed(&isCollapsed); + if (NS_FAILED(rv)) return rv; + + // Parent and offset under the mouse cursor + nsCOMPtr newSelectionParent; + PRInt32 newSelectionOffset = 0; + rv = nsuiEvent->GetRangeParent(getter_AddRefs(newSelectionParent)); + if (NS_FAILED(rv)) return rv; + if (!newSelectionParent) return NS_ERROR_FAILURE; - doPlaceCaret = PR_FALSE; - } - - rv = InsertFromTransferable(trans); + rv = nsuiEvent->GetRangeOffset(&newSelectionOffset); + if (NS_FAILED(rv)) return rv; + + // 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?rv:NS_ERROR_FAILURE; + + for (PRInt32 j = 0; j < rangeCount; j++) + { + nsCOMPtr range; + + rv = selection->GetRangeAt(j, getter_AddRefs(range)); + if (NS_FAILED(rv) || !range) + continue;//dont bail yet, iterate through them all + + nsCOMPtr 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 + selection->Collapse(newSelectionParent, newSelectionOffset); + } + + // We have to figure out whether to delete and relocate caret only once + doPlaceCaret = PR_FALSE; } + + rv = InsertFromTransferable(trans); } return rv; @@ -5090,7 +5166,19 @@ NS_IMETHODIMP nsHTMLEditor::CanDrag(nsIDOMEvent *aDragEvent, PRBool &aCanDrag) * that particular point is actually within the selection (not just that there is a selection) */ aCanDrag = PR_FALSE; - + + // KLUDGE to work around bug 50703 + // After double click and object property editing, + // we get a spurious drag event + if (mIgnoreSpuriousDragEvent) + { +#ifdef DEBUG_cmanske + printf(" *** IGNORING SPURIOUS DRAG EVENT!\n"); +#endif + mIgnoreSpuriousDragEvent = PR_FALSE; + return NS_OK; + } + nsCOMPtr selection; nsresult res = GetSelection(getter_AddRefs(selection)); if (NS_FAILED(res)) return res; diff --git a/mozilla/editor/base/nsHTMLEditor.h b/mozilla/editor/base/nsHTMLEditor.h index 841495e9319..b8bf71496c6 100644 --- a/mozilla/editor/base/nsHTMLEditor.h +++ b/mozilla/editor/base/nsHTMLEditor.h @@ -577,6 +577,10 @@ protected: nsresult GetDOMEventReceiver(nsIDOMEventReceiver **aEventReceiver); + //XXX Kludge: Used to suppress spurious drag/drop events (bug 50703) + PRBool mIgnoreSpuriousDragEvent; + NS_IMETHOD IgnoreSpuriousDragEvent(PRBool aIgnoreSpuriousDragEvent) {mIgnoreSpuriousDragEvent = aIgnoreSpuriousDragEvent; return NS_OK;} + // Data members protected: diff --git a/mozilla/editor/composer/src/nsComposerCommands.cpp b/mozilla/editor/composer/src/nsComposerCommands.cpp index 1272bf0bdf7..aae1aab7b36 100644 --- a/mozilla/editor/composer/src/nsComposerCommands.cpp +++ b/mozilla/editor/composer/src/nsComposerCommands.cpp @@ -474,9 +474,12 @@ nsRemoveListCommand::IsCommandEnabled(const PRUnichar *aCommand, nsISupports * r PRUnichar *tagStr; nsresult rv = editorShell->GetListState(&bMixed, &tagStr); if (NS_FAILED(rv)) return rv; - - *outCmdEnabled = (tagStr && *tagStr != nsnull); + if (bMixed) + *outCmdEnabled = PR_TRUE; + else + *outCmdEnabled = (tagStr && *tagStr); + if (tagStr) nsCRT::free(tagStr); } diff --git a/mozilla/editor/composer/src/nsEditorShellMouseListener.cpp b/mozilla/editor/composer/src/nsEditorShellMouseListener.cpp index 2a9a121325f..673348b40b8 100644 --- a/mozilla/editor/composer/src/nsEditorShellMouseListener.cpp +++ b/mozilla/editor/composer/src/nsEditorShellMouseListener.cpp @@ -31,10 +31,16 @@ #include "nsIDOMCharacterData.h" #include "nsIDOMMouseEvent.h" #include "nsIDOMSelection.h" +#include "nsIDOMRange.h" +#include "nsIDOMNSRange.h" #include "nsIDOMEventTarget.h" +#include "nsIDOMNSUIEvent.h" #include "nsIDOMHTMLTableElement.h" #include "nsIDOMHTMLTableCellElement.h" +#include "nsIEditor.h" +#include "nsIHTMLEditor.h" + /* * nsEditorShellMouseListener implementation */ @@ -160,104 +166,144 @@ nsEditorShellMouseListener::MouseDown(nsIDOMEvent* aMouseEvent) //non-ui event passed in. bad things. return NS_OK; } - - PRUint16 buttonNumber; - nsresult res = mouseEvent->GetButton(&buttonNumber); + // Don't do anything special if not an HTML editor + nsCOMPtr editor; + nsresult res = mEditorShell->GetEditor(getter_AddRefs(editor)); if (NS_FAILED(res)) return res; - PRBool isContextClick; - // Test if special 'table selection' key is pressed when double-clicking - // so we look for an enclosing cell or table - PRBool tableMode = PR_FALSE; - -#ifdef XP_MAC - // Cmd is Mac table-select key - res = mouseEvent->GetMetaKey(&tableMode); - if (NS_FAILED(res)) return res; - - // Ctrl+Click for context menu - res = mouseEvent->GetCtrlKey(&isContextClick); -#else - // Right mouse button for Windows, UNIX - isContextClick = buttonNumber == 3; - res = mouseEvent->GetCtrlKey(&tableMode); -#endif - if (NS_FAILED(res)) return res; - - nsCOMPtr target; - res = aMouseEvent->GetTarget(getter_AddRefs(target)); - if (NS_FAILED(res)) return res; - if (!target) return NS_ERROR_NULL_POINTER; - nsCOMPtr element = do_QueryInterface(target); - - PRInt32 clickCount; - res = mouseEvent->GetDetail(&clickCount); - if (NS_FAILED(res)) return res; - - PRBool NodeIsInSelection = PR_FALSE; - - if (isContextClick || (buttonNumber == 1 && clickCount == 2)) + nsCOMPtr htmlEditor = do_QueryInterface(editor); + if (htmlEditor) { - // Context menu or double click - nsCOMPtr node = do_QueryInterface(target); - if (node) + PRUint16 buttonNumber; + res = mouseEvent->GetButton(&buttonNumber); + if (NS_FAILED(res)) return res; + + PRBool isContextClick; + // Test if special 'table selection' key is pressed when double-clicking + // so we look for an enclosing cell or table + PRBool tableMode = PR_FALSE; + + #ifdef XP_MAC + // Cmd is Mac table-select key + res = mouseEvent->GetMetaKey(&tableMode); + if (NS_FAILED(res)) return res; + + // Ctrl+Click for context menu + res = mouseEvent->GetCtrlKey(&isContextClick); + #else + // Right mouse button for Windows, UNIX + isContextClick = buttonNumber == 3; + res = mouseEvent->GetCtrlKey(&tableMode); + #endif + if (NS_FAILED(res)) return res; + + nsCOMPtr target; + res = aMouseEvent->GetTarget(getter_AddRefs(target)); + if (NS_FAILED(res)) return res; + if (!target) return NS_ERROR_NULL_POINTER; + nsCOMPtr element = do_QueryInterface(target); + + PRInt32 clickCount; + res = mouseEvent->GetDetail(&clickCount); + if (NS_FAILED(res)) return res; + + nsCOMPtr selection; + mEditorShell->GetEditorSelection(getter_AddRefs(selection)); + if (!selection) return NS_OK; + + nsCOMPtr parent; + PRInt32 offset = 0; + + // Get location of mouse within target node + nsCOMPtr uiEvent = do_QueryInterface(aMouseEvent); + if (!uiEvent) return NS_ERROR_FAILURE; + + res = uiEvent->GetRangeParent(getter_AddRefs(parent)); + if (NS_FAILED(res)) return res; + if (!parent) return NS_ERROR_FAILURE; + + res = uiEvent->GetRangeOffset(&offset); + if (NS_FAILED(res)) return res; + + // Detect if mouse point is withing current selection + PRBool NodeIsInSelection = PR_FALSE; + PRBool isCollapsed; + selection->GetIsCollapsed(&isCollapsed); + + if (!isCollapsed) { - nsCOMPtr selection; - mEditorShell->GetEditorSelection(getter_AddRefs(selection)); - if (selection) + PRInt32 rangeCount; + res = selection->GetRangeCount(&rangeCount); + if (NS_FAILED(res)) return res; + + for (PRInt32 i = 0; i < rangeCount; i++) { - res = selection->ContainsNode(node, PR_TRUE, &NodeIsInSelection); - // Kludge: We really want to reposition the caret exactly as done for - // left mouse button, but we never reach the frame's HandlePress method. - // Thus for text nodes, the best we can do is reposition to the start of the node, - // but only if not already selected, of course - if (!NodeIsInSelection) - selection->Collapse(node, 0); + nsCOMPtr range; + + res = selection->GetRangeAt(i, getter_AddRefs(range)); + if (NS_FAILED(res) || !range) + continue;//dont bail yet, iterate through them all + + nsCOMPtr nsrange(do_QueryInterface(range)); + if (NS_FAILED(res) || !nsrange) + continue;//dont bail yet, iterate through them all + + res = nsrange->IsPointInRange(parent, offset, &NodeIsInSelection); } - - // Get enclosing link - nsCOMPtr linkElement; - res = mEditorShell->GetElementOrParentByTagName(NS_LITERAL_STRING("href"), node, getter_AddRefs(linkElement)); - if (NS_FAILED(res)) return res; - if (linkElement) - element = linkElement; } - } - if (isContextClick) - { - // Set selection to node clicked on if NOT within an existing selection - if (element && !NodeIsInSelection) - mEditorShell->SelectElement(element); - // Always fall through to do other actions, such as context menu - } - else if (buttonNumber == 1) - { -#ifdef DEBUG_cmanske -// printf("nsEditorShellMouseListener::MouseDown: clickCount=%d\n",clickCount); -#endif - - if (tableMode && clickCount == 2) + if (isContextClick || (buttonNumber == 1 && clickCount == 2)) { - if (!GetParentCell(aMouseEvent, getter_AddRefs(element))) - GetParentTable(aMouseEvent, getter_AddRefs(element)); + // Context menu or double click + nsCOMPtr node = do_QueryInterface(target); + if (node && !NodeIsInSelection) + { + selection->Collapse(parent, offset); + + // Get enclosing link + nsCOMPtr linkElement; + res = mEditorShell->GetElementOrParentByTagName(NS_LITERAL_STRING("href"), node, getter_AddRefs(linkElement)); + if (NS_FAILED(res)) return res; + if (linkElement) + element = linkElement; + } } - // No table or cell -- look for other element (ignore text nodes) - if (element) + + if (isContextClick) { - PRInt32 x,y; - res = mouseEvent->GetClientX(&x); - if (NS_FAILED(res)) return res; + // Set selection to node clicked on if NOT within an existing selection + if (element && !NodeIsInSelection) + mEditorShell->SelectElement(element); + // Always fall through to do other actions, such as context menu + } + else if (buttonNumber == 1) + { + if (tableMode && clickCount == 2) + { + if (!GetParentCell(aMouseEvent, getter_AddRefs(element))) + GetParentTable(aMouseEvent, getter_AddRefs(element)); + } + // No table or cell -- look for other element (ignore text nodes) + if (element) + { + PRInt32 x,y; + res = mouseEvent->GetClientX(&x); + if (NS_FAILED(res)) return res; - res = mouseEvent->GetClientY(&y); - if (NS_FAILED(res)) return res; + res = mouseEvent->GetClientY(&y); + if (NS_FAILED(res)) return res; - // Let editor decide what to do with this - PRBool handled = PR_FALSE; - mEditorShell->HandleMouseClickOnElement(element, clickCount, x, y, &handled); + // KLUDGE to work around bug 50703: Prevent drag/drop events until we are done + if (clickCount == 2) + htmlEditor->IgnoreSpuriousDragEvent(PR_TRUE); - if (handled) - mouseEvent->PreventDefault(); + // Let editor decide what to do with this + PRBool handled = PR_FALSE; + mEditorShell->HandleMouseClickOnElement(element, clickCount, x, y, &handled); + + if (handled) + mouseEvent->PreventDefault(); + } } } @@ -267,10 +313,7 @@ nsEditorShellMouseListener::MouseDown(nsIDOMEvent* aMouseEvent) nsresult nsEditorShellMouseListener::MouseUp(nsIDOMEvent* aMouseEvent) { -#ifdef DEBUG_cmanske -printf("* nsEditorShellMouseListener::MouseUp message\n"); -#endif - return NS_OK; // didn't handle event + return NS_OK; } nsresult diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp index 29f0d3f7064..268f34855e5 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.cpp +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.cpp @@ -239,6 +239,7 @@ nsHTMLEditor::nsHTMLEditor() , mIsComposing(PR_FALSE) , mMaxTextLength(-1) , mSelectedCellIndex(0) +, mIgnoreSpuriousDragEvent(PR_FALSE) { // Done in nsEditor // NS_INIT_REFCNT(); @@ -2620,7 +2621,7 @@ nsHTMLEditor::ReplaceHeadContentsWithHTML(const nsString &aSourceToInsert) res = nsrange->CreateContextualFragment(inputString, getter_AddRefs(docfrag)); - //XXXX BUG: This is not returning the text between ... + //XXXX BUG 50965: This is not returning the text between ... // Special code is needed in JS to handle title anyway, so it really doesn't matter! if (NS_FAILED(res)) @@ -5000,7 +5001,6 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromTransferable(nsITransferable *transferable return rv; } - NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent) { ForceCompositionEnd(); @@ -5011,74 +5011,150 @@ NS_IMETHODIMP nsHTMLEditor::InsertFromDrop(nsIDOMEvent* aDropEvent) nsCOMPtr dragSession(do_QueryInterface(dragService)); - if (dragSession) + if (!dragSession) return NS_OK; + + // Get the nsITransferable interface for getting the data from the drop + nsCOMPtr 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) { - // Get the nsITransferable interface for getting the data from the drop - nsCOMPtr trans; - rv = PrepareTransferable(getter_AddRefs(trans)); - if (NS_SUCCEEDED(rv) && trans) + rv = dragSession->GetData(trans, i); + if (NS_FAILED(rv)) return rv; + if (!trans) return NS_OK; // NS_ERROR_FAILURE; Should we fail? + + if ( doPlaceCaret ) { - PRUint32 numItems = 0; - if (NS_SUCCEEDED(dragSession->GetNumDropItems(&numItems))) - { - PRUint32 i; - PRBool doPlaceCaret = PR_TRUE; - for (i = 0; i < numItems; ++i) - { - if (NS_SUCCEEDED(dragSession->GetData(trans, i))) - { - 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 mouseEvent ( do_QueryInterface(aDropEvent) ); - if (mouseEvent) + // 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 nsuiEvent (do_QueryInterface(aDropEvent)); + if (!nsuiEvent) return NS_ERROR_FAILURE; + + nsCOMPtr mouseEvent ( do_QueryInterface(aDropEvent) ); + if (mouseEvent) + #ifdef XP_MAC - mouseEvent->GetAltKey(&userWantsCopy); // check modifiers here + mouseEvent->GetAltKey(&userWantsCopy); #else - mouseEvent->GetCtrlKey(&userWantsCopy); // check modifiers here + mouseEvent->GetCtrlKey(&userWantsCopy); #endif - - nsCOMPtr srcdomdoc; - dragSession->GetSourceDocument(getter_AddRefs(srcdomdoc)); - if (srcdomdoc) - { - // do deletion of selection if sourcedocument is current document && appropriate modifier isn't pressed - nsCOMPtrdestdomdoc; - rv = GetDocument(getter_AddRefs(destdomdoc)); - if ( NS_SUCCEEDED(rv) && !userWantsCopy && (srcdomdoc == destdomdoc) ) - { - rv = DeleteSelection(eNone); - if (NS_FAILED(rv)) - return rv; - } - } + // Source doc is null if source is *not* the current editor document + nsCOMPtr srcdomdoc; + rv = dragSession->GetSourceDocument(getter_AddRefs(srcdomdoc)); + if (NS_FAILED(rv)) return rv; - // Set the selection to the point under the mouse cursor: - nsCOMPtr nsuiEvent (do_QueryInterface(aDropEvent)); + // Current doc is destination + nsCOMPtrdestdomdoc; + rv = GetDocument(getter_AddRefs(destdomdoc)); + if (NS_FAILED(rv)) return rv; - if (!nsuiEvent) - return NS_ERROR_NULL_POINTER; - nsCOMPtr parent; - if (!NS_SUCCEEDED(nsuiEvent->GetRangeParent(getter_AddRefs(parent)))) - return NS_ERROR_NULL_POINTER; - PRInt32 offset = 0; - if (!NS_SUCCEEDED(nsuiEvent->GetRangeOffset(&offset))) - return NS_ERROR_NULL_POINTER; + nsCOMPtr selection; + rv = GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(rv)) return rv; + if (!selection) return NS_ERROR_FAILURE; - nsCOMPtr selection; - if (NS_SUCCEEDED(GetSelection(getter_AddRefs(selection)))) - (void)selection->Collapse(parent, offset); + PRBool isCollapsed; + rv = selection->GetIsCollapsed(&isCollapsed); + if (NS_FAILED(rv)) return rv; + + // Parent and offset under the mouse cursor + nsCOMPtr newSelectionParent; + PRInt32 newSelectionOffset = 0; + rv = nsuiEvent->GetRangeParent(getter_AddRefs(newSelectionParent)); + if (NS_FAILED(rv)) return rv; + if (!newSelectionParent) return NS_ERROR_FAILURE; - doPlaceCaret = PR_FALSE; - } - - rv = InsertFromTransferable(trans); + rv = nsuiEvent->GetRangeOffset(&newSelectionOffset); + if (NS_FAILED(rv)) return rv; + + // 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?rv:NS_ERROR_FAILURE; + + for (PRInt32 j = 0; j < rangeCount; j++) + { + nsCOMPtr range; + + rv = selection->GetRangeAt(j, getter_AddRefs(range)); + if (NS_FAILED(rv) || !range) + continue;//dont bail yet, iterate through them all + + nsCOMPtr 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 + selection->Collapse(newSelectionParent, newSelectionOffset); + } + + // We have to figure out whether to delete and relocate caret only once + doPlaceCaret = PR_FALSE; } + + rv = InsertFromTransferable(trans); } return rv; @@ -5090,7 +5166,19 @@ NS_IMETHODIMP nsHTMLEditor::CanDrag(nsIDOMEvent *aDragEvent, PRBool &aCanDrag) * that particular point is actually within the selection (not just that there is a selection) */ aCanDrag = PR_FALSE; - + + // KLUDGE to work around bug 50703 + // After double click and object property editing, + // we get a spurious drag event + if (mIgnoreSpuriousDragEvent) + { +#ifdef DEBUG_cmanske + printf(" *** IGNORING SPURIOUS DRAG EVENT!\n"); +#endif + mIgnoreSpuriousDragEvent = PR_FALSE; + return NS_OK; + } + nsCOMPtr selection; nsresult res = GetSelection(getter_AddRefs(selection)); if (NS_FAILED(res)) return res; diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.h b/mozilla/editor/libeditor/html/nsHTMLEditor.h index 841495e9319..b8bf71496c6 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.h +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.h @@ -577,6 +577,10 @@ protected: nsresult GetDOMEventReceiver(nsIDOMEventReceiver **aEventReceiver); + //XXX Kludge: Used to suppress spurious drag/drop events (bug 50703) + PRBool mIgnoreSpuriousDragEvent; + NS_IMETHOD IgnoreSpuriousDragEvent(PRBool aIgnoreSpuriousDragEvent) {mIgnoreSpuriousDragEvent = aIgnoreSpuriousDragEvent; return NS_OK;} + // Data members protected: diff --git a/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp b/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp index 5679cbbb66e..7c6076ac5c7 100644 --- a/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp +++ b/mozilla/editor/libeditor/text/nsEditorEventListeners.cpp @@ -682,11 +682,11 @@ nsTextEditorDragListener::DragDrop(nsIDOMEvent* aMouseEvent) { nsresult rv; NS_WITH_SERVICE(nsIDragService, dragService, "component://netscape/widget/dragservice", &rv); - if (NS_FAILED(rv)) return rv; + if (NS_FAILED(rv)) return rv; nsCOMPtr dragSession(do_QueryInterface(dragService)); if (dragSession) - { + { PRBool flavorSupported = PR_FALSE; dragSession->IsDataFlavorSupported(kUnicodeMime, &flavorSupported); if ( !flavorSupported ) @@ -696,54 +696,73 @@ nsTextEditorDragListener::DragDrop(nsIDOMEvent* aMouseEvent) if ( !flavorSupported ) dragSession->IsDataFlavorSupported(kJPEGImageMime, &flavorSupported); if (! flavorSupported ) - return NS_OK; - } + return NS_OK; + } + nsCOMPtr nsuiEvent (do_QueryInterface(aMouseEvent)); + if (!nsuiEvent) return NS_OK; //some day we want to use another way to stop this from bubbling. aMouseEvent->PreventBubble(); aMouseEvent->PreventDefault(); /* for bug 47399, when dropping a drag session, if you are over your original - selection, nothing should happen. */ - nsCOMPtr tempSelection; - rv = mEditor->GetSelection(getter_AddRefs(tempSelection)); - if (NS_FAILED(rv) || !tempSelection) + selection, nothing should happen. + cmanske: But do this only if drag source is not the same as target (current) document! + */ + nsCOMPtr selection; + rv = mEditor->GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(rv) || !selection) return rv?rv:NS_ERROR_FAILURE; - PRInt32 rangeCount; - rv = tempSelection->GetRangeCount(&rangeCount); - if (NS_FAILED(rv)) - return rv?rv:NS_ERROR_FAILURE; + nsCOMPtr editor = do_QueryInterface(htmlEditor); + nsCOMPtr domdoc; + rv = editor->GetDocument(getter_AddRefs(domdoc)); + if (NS_FAILED(rv)) return rv; - for(int i = 0; i < rangeCount; i++) + nsCOMPtr sourceDoc; + rv = dragSession->GetSourceDocument(getter_AddRefs(sourceDoc)); + if (NS_FAILED(rv)) return rv; + if (domdoc == sourceDoc) { - nsCOMPtr range; + PRBool isCollapsed; + rv = selection->GetIsCollapsed(&isCollapsed); + if (NS_FAILED(rv)) return rv; + + // Don't bother if collapsed - can always drop + if (!isCollapsed) + { + nsCOMPtr parent; + rv = nsuiEvent->GetRangeParent(getter_AddRefs(parent)); + if (NS_FAILED(rv)) return rv; + if (!parent) return NS_ERROR_FAILURE; - rv = tempSelection->GetRangeAt(i, getter_AddRefs(range)); - if (NS_FAILED(rv) || !range) - continue;//dont bail yet, iterate through them all + PRInt32 offset = 0; + rv = nsuiEvent->GetRangeOffset(&offset); + if (NS_FAILED(rv)) return rv; - nsCOMPtr nsrange(do_QueryInterface(range)); - if (NS_FAILED(rv) || !nsrange) - continue;//dont bail yet, iterate through them all + PRInt32 rangeCount; + rv = selection->GetRangeCount(&rangeCount); + if (NS_FAILED(rv)) return rv; - nsCOMPtr nsuiEvent (do_QueryInterface(aMouseEvent)); - if (!nsuiEvent) - continue;//dont bail yet, iterate through them all + for (PRInt32 i = 0; i < rangeCount; i++) + { + nsCOMPtr range; - nsCOMPtr parent; - if (!NS_SUCCEEDED(nsuiEvent->GetRangeParent(getter_AddRefs(parent)))) - continue;//dont bail yet, iterate through them all + rv = selection->GetRangeAt(i, getter_AddRefs(range)); + if (NS_FAILED(rv) || !range) + continue;//dont bail yet, iterate through them all - PRInt32 offset = 0; - if (!NS_SUCCEEDED(nsuiEvent->GetRangeOffset(&offset))) - continue;//dont bail yet, iterate through them all + nsCOMPtr nsrange(do_QueryInterface(range)); + if (NS_FAILED(rv) || !nsrange) + continue;//dont bail yet, iterate through them all - PRBool inrange; - rv = nsrange->IsPointInRange(parent, offset, &inrange); - if(inrange) - return NS_ERROR_FAILURE;//okay, now you can bail, we are over the orginal selection + PRBool inrange; + rv = nsrange->IsPointInRange(parent, offset, &inrange); + if(inrange) + return NS_ERROR_FAILURE;//okay, now you can bail, we are over the orginal selection + } + } } // if we are not over orginal selection, drop that baby! return htmlEditor->InsertFromDrop(aMouseEvent); diff --git a/mozilla/editor/public/nsIHTMLEditor.h b/mozilla/editor/public/nsIHTMLEditor.h index e1ca73d3970..ac81c16a78e 100644 --- a/mozilla/editor/public/nsIHTMLEditor.h +++ b/mozilla/editor/public/nsIHTMLEditor.h @@ -466,19 +466,26 @@ public: */ NS_IMETHOD InsertLinkAroundSelection(nsIDOMElement* aAnchorElement)=0; - /** - * Document me! - * - */ + /** Set the value of the "bgcolor" attribute on the document's element + * + * @param aColor The HTML color string, such as "#ffccff" or "yellow" + */ NS_IMETHOD SetBackgroundColor(const nsString& aColor)=0; - /** - * Document me! - * - */ + /** Set an attribute on the document's element + * such as text, link, background colors + * + * 8/31/00 THIS ISN'T BEING USED? SHOULD WE DROP IT? + * + * @param aAttr The attribute to be set + * @param aValue The value of the attribute + */ NS_IMETHOD SetBodyAttribute(const nsString& aAttr, const nsString& aValue)=0; + //XXX Used to suppress spurious drag/drop events to workaround bug 50703 + // Don't use this method! It will go away after first release! + NS_IMETHOD IgnoreSpuriousDragEvent(PRBool aIgnoreSpuriousDragEvent)=0; }; diff --git a/mozilla/editor/ui/dialogs/content/EdColorProps.js b/mozilla/editor/ui/dialogs/content/EdColorProps.js index 2c92986d48b..6add33561a5 100644 --- a/mozilla/editor/ui/dialogs/content/EdColorProps.js +++ b/mozilla/editor/ui/dialogs/content/EdColorProps.js @@ -362,8 +362,6 @@ function ValidateAndPreviewImage(ShowErrorMessage) } else backgroundImage = null; -dump("ValidateAndPreviewImage: styleValue ="+styleValue+"\n"); - // Set style on preview (removes image if not valid) dialog.ColorPreview.setAttribute(styleStr, styleValue);