diff --git a/widget/src/mac/nsMimeMapper.cpp b/widget/src/mac/nsMimeMapper.cpp
index c292992ee448..cc96e7dc3321 100644
--- a/widget/src/mac/nsMimeMapper.cpp
+++ b/widget/src/mac/nsMimeMapper.cpp
@@ -69,8 +69,10 @@ nsMimeMapperMac :: MapMimeTypeToMacOSType ( const char* aMimeStr, PRBool inAddIf
// first check if it is already in our list.
for ( MimeMapConstIterator it = mMappings.begin(); it != mMappings.end(); ++it ) {
- if ( it->second == aMimeStr )
+ if ( it->second == aMimeStr ) {
format = it->first;
+ break;
+ }
}
// if it's not there, do a mapping and put it there. Some things we want to map
diff --git a/xpfe/components/bookmarks/resources/bm-panel.js b/xpfe/components/bookmarks/resources/bm-panel.js
index 0f922b70deae..1b16458f9b6a 100644
--- a/xpfe/components/bookmarks/resources/bm-panel.js
+++ b/xpfe/components/bookmarks/resources/bm-panel.js
@@ -77,3 +77,39 @@ function OpenBookmarkURL(node, datasources)
}
}
+
+function getAbsoluteID(root, node)
+{
+ var url = node.getAttribute("ref");
+ if ((url == null) || (url == ""))
+ {
+ url = node.getAttribute("id");
+ }
+ try
+ {
+ var rootNode = document.getElementById(root);
+ var ds = null;
+ if (rootNode)
+ {
+ ds = rootNode.database;
+ }
+
+ // add support for anonymous resources such as Internet Search results,
+ // IE favorites under Win32, and NetPositive URLs under BeOS
+ var rdf = Components.classes["component://netscape/rdf/rdf-service"].getService();
+ if (rdf) rdf = rdf.QueryInterface(Components.interfaces.nsIRDFService);
+ if (rdf && ds)
+ {
+ var src = rdf.GetResource(url, true);
+ var prop = rdf.GetResource("http://home.netscape.com/NC-rdf#URL", true);
+ var target = ds.GetTarget(src, prop, true);
+ if (target) target = target.QueryInterface(Components.interfaces.nsIRDFLiteral);
+ if (target) target = target.Value;
+ if (target) url = target;
+ }
+ }
+ catch(ex)
+ {
+ }
+ return(url);
+}
diff --git a/xpfe/components/bookmarks/resources/bm-panel.xul b/xpfe/components/bookmarks/resources/bm-panel.xul
index 31a6c7e36a3f..9b9a051430cd 100644
--- a/xpfe/components/bookmarks/resources/bm-panel.xul
+++ b/xpfe/components/bookmarks/resources/bm-panel.xul
@@ -29,9 +29,11 @@
xmlns:html="http://www.w3.org/TR/REC-html40"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ ondraggesture="return TopLevelDrag(event);"
align="vertical">
+
@@ -42,6 +44,9 @@
diff --git a/xpfe/components/bookmarks/resources/bookmarksDD.js b/xpfe/components/bookmarks/resources/bookmarksDD.js
index 3bc96b327a27..4e6aa60f11d9 100644
--- a/xpfe/components/bookmarks/resources/bookmarksDD.js
+++ b/xpfe/components/bookmarks/resources/bookmarksDD.js
@@ -45,9 +45,13 @@ catch (ex) {
}
+// XXX this currently controls whether bookmarks D&D is enabled or not
+gDragDropEnabled = true;
+
+
function TopLevelDrag ( event )
{
- debug("TOP LEVEL bookmarks window got a drag");
+ dump("TOP LEVEL bookmarks window got a drag");
return(true);
}
@@ -72,10 +76,6 @@ function BeginDragTree ( event )
var dragStarted = false;
- var dragService =
- Components.classes["component://netscape/widget/dragservice"].getService(Components.interfaces.nsIDragService);
- if ( !dragService ) return(false);
-
var trans =
Components.classes["component://netscape/widget/transferable"].createInstance(Components.interfaces.nsITransferable);
if ( !trans ) return(false);
@@ -84,14 +84,36 @@ function BeginDragTree ( event )
Components.classes["component://netscape/supports-wstring"].createInstance(Components.interfaces.nsISupportsWString);
if (!genData) return(false);
+ var genDataURL =
+ Components.classes["component://netscape/supports-wstring"].createInstance(Components.interfaces.nsISupportsWString);
+ if (!genDataURL) return(false);
+
trans.addDataFlavor("text/unicode");
+ trans.addDataFlavor("moz/rdfitem");
- // id (url) is on the which is two levels above the which is
+ // ref/id (url) is on the which is two levels above the which is
// the target of the event.
- var id = event.target.parentNode.parentNode.getAttribute("id");
- genData.data = id;
- genTextData.data = id;
- debug("ID: " + id);
+ var id = event.target.parentNode.parentNode.getAttribute("ref");
+ if (!id || id=="")
+ {
+ id = event.target.parentNode.parentNode.getAttribute("id");
+ }
+ dump("\n ID: " + id);
+
+ var parentID = event.target.parentNode.parentNode.parentNode.parentNode.getAttribute("ref");
+ if (!parentID || parentID == "")
+ {
+ parentID = event.target.parentNode.parentNode.parentNode.parentNode.getAttribute("id");
+ }
+ dump(" Parent ID: " + parentID);
+
+ var trueID = id;
+ if (parentID != null)
+ {
+ trueID += "\n" + parentID;
+ }
+ genData.data = trueID;
+ genDataURL.data = id;
var database = childWithDatabase.database;
var rdf =
@@ -106,15 +128,15 @@ function BeginDragTree ( event )
if (target) target = target.QueryInterface(Components.interfaces.nsIRDFResource);
if (target) target = target.Value;
if ((!target) || (target == "")) {dump("BAD\n"); return(false);}
- debug("Type: '" + target + "'");
+ dump(" Type: '" + target + "'");
if ((target != "http://home.netscape.com/NC-rdf#BookmarkSeparator") &&
(target != "http://home.netscape.com/NC-rdf#Bookmark") &&
(target != "http://home.netscape.com/NC-rdf#Folder")) return(false);
-
-// trans.setTransferData ( "moz/toolbaritem", genData, id.length*2 ); // double byte data (len*2)
- trans.setTransferData ( "text/unicode", genData, id.length * 2); // double byte data
+dump("genData is " + genData.data + " len is " + genData.data.length + "\n");
+ trans.setTransferData ( "moz/rdfitem", genData, genData.data.length * 2); // double byte data
+ trans.setTransferData ( "text/unicode", genDataURL, genDataURL.data.length * 2); // double byte data
var transArray =
Components.classes["component://netscape/supports-array"].createInstance(Components.interfaces.nsISupportsArray);
@@ -123,12 +145,17 @@ function BeginDragTree ( event )
// put it into the transferable as an |nsISupports|
var genTrans = trans.QueryInterface(Components.interfaces.nsISupports);
transArray.AppendElement(genTrans);
+
+ var dragService =
+ Components.classes["component://netscape/widget/dragservice"].getService(Components.interfaces.nsIDragService);
+ if ( !dragService ) return(false);
+
var nsIDragService = Components.interfaces.nsIDragService;
dragService.invokeDragSession ( transArray, null, nsIDragService.DRAGDROP_ACTION_COPY +
nsIDragService.DRAGDROP_ACTION_MOVE );
dragStarted = true;
- return(!dragStarted); // don't propagate the event if a drag has begun
+ return(!dragStarted);
}
@@ -136,7 +163,17 @@ function BeginDragTree ( event )
function DragOverTree ( event )
{
if ( !gDragDropEnabled )
- return;
+ return(false);
+
+ // for beta1, don't allow D&D if sorting is active
+ var tree = document.getElementById("bookmarksTree");
+ if (!tree) return(false);
+ var sortActive = tree.getAttribute("sortActive");
+ if (sortActive == "true")
+ {
+ dump("Sorry, drag&drop is currently disabled when sorting is active.\n");
+ return(false);
+ }
var validFlavor = false;
var dragSession = null;
@@ -149,7 +186,7 @@ function DragOverTree ( event )
dragSession = dragService.getCurrentSession();
if ( !dragSession ) return(false);
- if ( dragSession.isDataFlavorSupported("moz/toolbaritem") ) validFlavor = true;
+ if ( dragSession.isDataFlavorSupported("moz/rdfitem") ) validFlavor = true;
else if ( dragSession.isDataFlavorSupported("text/unicode") ) validFlavor = true;
//XXX other flavors here...
@@ -161,7 +198,7 @@ function DragOverTree ( event )
rowGroup.setAttribute ( "dd-triggerrepaint", 0 );
dragSession.canDrop = true;
// necessary??
- retVal = false; // do not propagate message
+ retVal = false;
}
return(retVal);
}
@@ -171,8 +208,21 @@ function DragOverTree ( event )
function DropOnTree ( event )
{
if ( !gDragDropEnabled )
- return;
-
+ return(false);
+
+ var treeRoot = document.getElementById("bookmarksTree");
+ if (!treeRoot) return(false);
+ var treeDatabase = treeRoot.database;
+ if (!treeDatabase) return(false);
+
+ // for beta1, don't allow D&D if sorting is active
+ var sortActive = treeRoot.getAttribute("sortActive");
+ if (sortActive == "true")
+ {
+ dump("Sorry, drag&drop is currently disabled when sorting is active.\n");
+ return(false);
+ }
+
var RDF =
Components.classes["component://netscape/rdf/rdf-service"].getService(Components.interfaces.nsIRDFService);
if (!RDF) return(false);
@@ -183,12 +233,7 @@ function DropOnTree ( event )
var Bookmarks = RDF.GetDataSource("rdf:bookmarks");
if (!Bookmarks) return(false);
- var treeRoot = document.getElementById("bookmarksTree");
- if (!treeRoot) return(false);
- var treeDatabase = treeRoot.database;
- if (!treeDatabase) return(false);
-
- // target is the , and "id" is on the two levels above
+ // target is the , and "ref/id" is on the two levels above
var treeItem = event.target.parentNode.parentNode;
if (!treeItem) return(false);
var targetID = getAbsoluteID(treeRoot, treeItem);
@@ -226,6 +271,7 @@ function DropOnTree ( event )
var trans =
Components.classes["component://netscape/widget/transferable"].createInstance(Components.interfaces.nsITransferable);
if ( !trans ) return(false);
+ trans.addDataFlavor("moz/rdfitem");
trans.addDataFlavor("text/unicode");
var dirty = false;
@@ -240,17 +286,49 @@ function DropOnTree ( event )
if ( dataObj ) dataObj = dataObj.value.QueryInterface(Components.interfaces.nsISupportsWString);
if ( !dataObj ) continue;
- // pull the URL out of the data object
- var sourceID = dataObj.data;
- if (!sourceID) continue;
+ var sourceID = null;
+ var parentID = null;
+ var checkNameHack = false;
- debug(" Node #" + i + ": drop '" + sourceID + "' " + dropAction + " '" + targetID + "'");
+ if (bestFlavor.value == "moz/rdfitem")
+ {
+ // pull the URL out of the data object
+ var data = dataObj.data.substring(0, len.value / 2);;
+
+ var cr = data.indexOf("\n");
+ if (cr >= 0)
+ {
+ sourceID = data.substr(0, cr);
+ parentID = data.substr(cr+1);
+ }
+ }
+ else
+ {
+ sourceID = dataObj.data;
+
+ // XXX for the moment, if its a text/unicode drop
+ // we may need to synthesize a name (just use the URL)
+ checkNameHack = true;
+ }
+
+ dump(" Node #" + i + ": drop '" + sourceID + "'\n");
+ dump(" from container '" + parentID + "'\n");
+ dump(" action = '" + dropAction + "'\n");
+ dump(" target = '" + targetID + "'\n");
var sourceNode = RDF.GetResource(sourceID, true);
if (!sourceNode) continue;
+
+ var parentNode = null;
+ if (parentID != null)
+ {
+ parentNode = RDF.GetResource(parentID, true);
+ }
// Prevent dropping of a node before, after, or on itself
if (sourceNode == targetNode) continue;
+ // Prevent dropping of a node onto its parent container
+ if ((dropAction == "on") && (containerID) && (containerID == parentID)) continue;
RDFC.Init(Bookmarks, containerNode);
@@ -260,6 +338,7 @@ function DropOnTree ( event )
var nodeIndex;
nodeIndex = RDFC.IndexOf(sourceNode);
+
if (nodeIndex >= 1)
{
// moving a node around inside of the container
@@ -268,29 +347,104 @@ function DropOnTree ( event )
}
nodeIndex = RDFC.IndexOf(targetNode);
+
if (nodeIndex < 1) return(false);
if (dropAction == "after") ++nodeIndex;
RDFC.InsertElementAt(sourceNode, nodeIndex, true);
+
+ // select the newly added node
+ if (parentID)
+ {
+ selectDroppedItems(treeRoot, containerID, sourceID);
+ }
+
dirty = true;
}
else
{
// drop on
RDFC.AppendElement(sourceNode);
+
+ // select the newly added node
+ if (parentID)
+ {
+ selectDroppedItems(treeRoot, containerID, sourceID);
+ }
+
dirty = true;
}
+
+ if (checkNameHack == true)
+ {
+ // XXX for the moment, if its a text/unicode drop
+ // we may need to synthesize a name (just use the URL)
+ var srcArc = RDF.GetResource(sourceID, true);
+ var propArc = RDF.GetResource("http://home.netscape.com/NC-rdf#Name", true);
+ if (srcArc && propArc && treeDatabase)
+ {
+ var targetArc = treeDatabase.GetTarget(srcArc, propArc, true);
+ if (!targetArc)
+ {
+ var defaultNameArc = RDF.GetLiteral(sourceID);
+ if (defaultNameArc)
+ {
+ treeDatabase.Assert(srcArc, propArc, defaultNameArc, true);
+ }
+ }
+ }
+ }
}
+ // should we move the node? (i.e. take it out of the source container?)
+ if ((parentNode != null) && (containerNode != parentNode))
+ {
+ RDFC.Init(Bookmarks, parentNode);
+ var nodeIndex = RDFC.IndexOf(sourceNode);
+
+ if (nodeIndex >= 1)
+ {
+ RDFC.RemoveElementAt(nodeIndex, true, sourceNode);
+ }
+ }
+
if (dirty == true)
{
var remote = Bookmarks.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
if (remote)
{
remote.Flush();
- debug("Wrote out bookmark changes.");
+ dump("Wrote out bookmark changes.");
}
}
return(false);
}
+
+
+
+function selectDroppedItems(treeRoot, containerID, targetID)
+{
+ var select_list = treeRoot.getElementsByAttribute("id", targetID);
+ for (var x=0; x