950 lines
40 KiB
Diff
950 lines
40 KiB
Diff
Index: widget/src/gtk2/nsClipboard.cpp
|
|
===================================================================
|
|
RCS file: /export/src/cvs/mozilla1.7/mozilla/widget/src/gtk2/nsClipboard.cpp,v
|
|
retrieving revision 1.1.1.1
|
|
diff -u -r1.1.1.1 nsClipboard.cpp
|
|
--- widget/src/gtk2/nsClipboard.cpp 2004/04/13 06:46:17 1.1.1.1
|
|
+++ widget/src/gtk2/nsClipboard.cpp 2004/04/13 08:22:00
|
|
@@ -73,7 +73,7 @@
|
|
GdkEventSelection *aEvent,
|
|
nsClipboard *aClipboard);
|
|
|
|
-static void
|
|
+void
|
|
ConvertHTMLtoUCS2 (guchar *data,
|
|
PRInt32 dataLength,
|
|
PRUnichar **unicodeData,
|
|
@@ -473,7 +473,6 @@
|
|
// utf-8.
|
|
|
|
PRInt32 whichClipboard;
|
|
-
|
|
// which clipboard?
|
|
if (aSelectionData->selection == GDK_SELECTION_PRIMARY)
|
|
whichClipboard = kSelectionClipboard;
|
|
@@ -547,16 +546,8 @@
|
|
* Byte Order Mark (BOM)). Adding BOM can help other app to
|
|
* detect mozilla use UCS2 encoding when copy-paste.
|
|
*/
|
|
- guchar *buffer = (guchar *)
|
|
- nsMemory::Alloc((len * sizeof(guchar)) + sizeof(PRUnichar));
|
|
- if (!buffer)
|
|
- return;
|
|
- PRUnichar prefix = 0xFEFF;
|
|
- memcpy(buffer, &prefix, sizeof(prefix));
|
|
- memcpy(buffer + sizeof(prefix), primitive_data, len);
|
|
- nsMemory::Free((guchar *)primitive_data);
|
|
- primitive_data = (guchar *)buffer;
|
|
- len += sizeof(prefix);
|
|
+ addBOM(NS_REINTERPRET_CAST(guchar **, &primitive_data),
|
|
+ NS_REINTERPRET_CAST(gint *, &len));
|
|
}
|
|
|
|
gtk_selection_data_set(aSelectionData, aSelectionData->target,
|
|
@@ -736,6 +727,22 @@
|
|
return;
|
|
}
|
|
str.AssignLiteral("UNKNOWN");
|
|
+}
|
|
+
|
|
+void addBOM(guchar **data, gint *len)
|
|
+{
|
|
+ guchar* indata = *data;
|
|
+ gint inlen = *len;
|
|
+ guchar *buffer = (guchar *)
|
|
+ nsMemory::Alloc((inlen * sizeof(guchar)) + sizeof(PRUnichar));
|
|
+ if (!buffer)
|
|
+ return;
|
|
+ PRUnichar prefix = 0xFEFF;
|
|
+ memcpy(buffer, &prefix, sizeof(prefix));
|
|
+ memcpy(buffer + sizeof(prefix), indata, inlen);
|
|
+ nsMemory::Free((guchar *)indata);
|
|
+ *data = (guchar *)buffer;
|
|
+ *len += sizeof(prefix);
|
|
}
|
|
|
|
static void
|
|
Index: widget/src/gtk2/nsClipboard.h
|
|
===================================================================
|
|
RCS file: /export/src/cvs/mozilla1.7/mozilla/widget/src/gtk2/nsClipboard.h,v
|
|
retrieving revision 1.1.1.1
|
|
diff -u -r1.1.1.1 nsClipboard.h
|
|
--- widget/src/gtk2/nsClipboard.h 2004/04/13 06:46:17 1.1.1.1
|
|
+++ widget/src/gtk2/nsClipboard.h 2004/04/13 08:22:00
|
|
@@ -87,4 +87,6 @@
|
|
|
|
};
|
|
|
|
+void addBOM(guchar **data, gint *len);
|
|
+
|
|
#endif /* __nsClipboard_h_ */
|
|
Index: widget/src/gtk2/nsDragService.cpp
|
|
===================================================================
|
|
RCS file: /export/src/cvs/mozilla1.7/mozilla/widget/src/gtk2/nsDragService.cpp,v
|
|
retrieving revision 1.1.1.1
|
|
diff -u -r1.1.1.1 nsDragService.cpp
|
|
--- widget/src/gtk2/nsDragService.cpp 2004/04/13 06:46:17 1.1.1.1
|
|
+++ widget/src/gtk2/nsDragService.cpp 2004/04/13 08:22:00
|
|
@@ -41,6 +41,8 @@
|
|
#include <gtk/gtkinvisible.h>
|
|
#include <gdk/gdkx.h>
|
|
#include "nsCRT.h"
|
|
+#include "nsString.h"
|
|
+#include "nsReadableUtils.h"
|
|
|
|
|
|
static PRLogModuleInfo *sDragLm = NULL;
|
|
@@ -49,6 +51,9 @@
|
|
static const char gMozUrlType[] = "_NETSCAPE_URL";
|
|
static const char gTextUriListType[] = "text/uri-list";
|
|
|
|
+static const char gPlainTextUTF16[] = "text/plain;charset=utf-16";
|
|
+static const char gPlainTextUTF8[] = "text/plain;charset=utf-8";
|
|
+
|
|
NS_IMPL_ADDREF_INHERITED(nsDragService, nsBaseDragService)
|
|
NS_IMPL_RELEASE_INHERITED(nsDragService, nsBaseDragService)
|
|
NS_IMPL_QUERY_INTERFACE4(nsDragService,
|
|
@@ -57,6 +62,10 @@
|
|
nsIDragSessionGTK,
|
|
nsIObserver)
|
|
|
|
+void addBOM(guchar **data, gint *len);
|
|
+void ConvertHTMLtoUCS2(guchar * data, PRInt32 dataLength,
|
|
+ PRUnichar** unicodeData, PRInt32& outUnicodeLen);
|
|
+
|
|
static void
|
|
invisibleSourceDragEnd(GtkWidget *aWidget,
|
|
GdkDragContext *aContext,
|
|
@@ -70,6 +79,38 @@
|
|
guint32 aTime,
|
|
gpointer aData);
|
|
|
|
+struct AutoConvertTargetPair {
|
|
+ const char * internal; // the drag data receiving side
|
|
+ const char * outside; // the drag data providing side
|
|
+ TargetConverter out2in;
|
|
+ TargetConverter in2out;
|
|
+};
|
|
+
|
|
+//converters
|
|
+static void utf8_to_ucs2 (const char *aDataIn, unsigned int aDataInLen,
|
|
+ char **aDataOut, unsigned int *aDataOutLen);
|
|
+static void ucs2_to_text (const char *aDataIn, unsigned int aDataInLen,
|
|
+ char **aDataOut, unsigned int *aDataOutLen);
|
|
+static void text_to_ucs2 (const char *aDataIn, unsigned int aDataInLen,
|
|
+ char **aDataOut, unsigned int *aDataOutLen);
|
|
+
|
|
+// The table used to match an internal target to an outside target
|
|
+// the entry comes early has high priority in matching
|
|
+static const AutoConvertTargetPair autoConvertPair[] = {
|
|
+ {kUnicodeMime, "UTF8_STRING", utf8_to_ucs2, ucs2_to_text},
|
|
+ {kUnicodeMime, "COMPOUND_TEXT", utf8_to_ucs2, ucs2_to_text},
|
|
+ {kUnicodeMime, "TEXT", utf8_to_ucs2, ucs2_to_text},
|
|
+ {kUnicodeMime, "STRING", utf8_to_ucs2, ucs2_to_text},
|
|
+ {kUnicodeMime, kTextMime, text_to_ucs2, ucs2_to_text},
|
|
+ {kUnicodeMime, gPlainTextUTF16, NULL, NULL},
|
|
+ {kUnicodeMime, gPlainTextUTF8, text_to_ucs2, ucs2_to_text},
|
|
+
|
|
+ {kURLMime, gTextUriListType, NULL, ucs2_to_text},
|
|
+ {kURLMime, gMozUrlType, text_to_ucs2, ucs2_to_text},
|
|
+
|
|
+ {NULL, NULL, NULL, NULL},
|
|
+};
|
|
+
|
|
nsDragService::nsDragService()
|
|
{
|
|
// We have to destroy the hidden widget before the event loop stops
|
|
@@ -92,7 +133,7 @@
|
|
|
|
// set up our logging module
|
|
if (!sDragLm)
|
|
- sDragLm = PR_NewLogModule("nsDragService");
|
|
+ sDragLm = PR_NewLogModule("nsDragService");
|
|
PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::nsDragService"));
|
|
mTargetWidget = 0;
|
|
mTargetDragContext = 0;
|
|
@@ -101,6 +142,8 @@
|
|
mTargetDragDataReceived = PR_FALSE;
|
|
mTargetDragData = 0;
|
|
mTargetDragDataLen = 0;
|
|
+ mTargetDragGdkAtom = 0;
|
|
+ mTargetConverter = NULL;
|
|
}
|
|
|
|
nsDragService::~nsDragService()
|
|
@@ -173,6 +216,16 @@
|
|
event.button.window = mHiddenWidget->window;
|
|
event.button.time = nsWindow::mLastButtonPressTime;
|
|
|
|
+ event.button.send_event = 0;
|
|
+ event.button.x = 0;
|
|
+ event.button.y = 0;
|
|
+ event.button.state = 0;
|
|
+ event.button.button = 0;
|
|
+ event.button.device = 0;
|
|
+ event.button.x_root = 0;
|
|
+ event.button.y_root = 0;
|
|
+
|
|
+
|
|
// start our drag.
|
|
GdkDragContext *context = gtk_drag_begin(mHiddenWidget,
|
|
sourceList,
|
|
@@ -291,7 +344,7 @@
|
|
NS_IMETHODIMP
|
|
nsDragService::GetNumDropItems(PRUint32 * aNumItems)
|
|
{
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::GetNumDropItems"));
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG, ("==nsDragService::GetNumDropItems==\n"));
|
|
PRBool isList = IsTargetContextList();
|
|
if (isList)
|
|
mSourceDataItems->Count(aNumItems);
|
|
@@ -303,8 +356,9 @@
|
|
*aNumItems = CountTextUriListItems(data, mTargetDragDataLen);
|
|
} else
|
|
*aNumItems = 1;
|
|
+ TargetResetData();
|
|
}
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG, ("%d items", *aNumItems));
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG, ("%d items\n", *aNumItems));
|
|
return NS_OK;
|
|
}
|
|
|
|
@@ -360,7 +414,7 @@
|
|
PRUint32 tmpDataLen = 0;
|
|
PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
("trying to get transfer data for %s\n",
|
|
- (const char *)flavorStr));
|
|
+ (const char *)flavorStr));
|
|
rv = item->GetTransferData(flavorStr,
|
|
getter_AddRefs(data),
|
|
&tmpDataLen);
|
|
@@ -387,6 +441,7 @@
|
|
// Now walk down the list of flavors. When we find one that is
|
|
// actually present, copy out the data into the transferable in that
|
|
// format. SetTransferData() implicitly handles conversions.
|
|
+
|
|
for ( i = 0; i < cnt; ++i ) {
|
|
nsCOMPtr<nsISupports> genericWrapper;
|
|
flavorList->GetElementAt(i,getter_AddRefs(genericWrapper));
|
|
@@ -399,118 +454,58 @@
|
|
GdkAtom gdkFlavor = gdk_atom_intern(flavorStr, FALSE);
|
|
PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
("looking for data in type %s, gdk flavor %ld\n",
|
|
- NS_STATIC_CAST(const char*,flavorStr), gdkFlavor));
|
|
+ NS_STATIC_CAST(const char*,flavorStr), gdkFlavor));
|
|
PRBool dataFound = PR_FALSE;
|
|
if (gdkFlavor) {
|
|
GetTargetDragData(gdkFlavor);
|
|
}
|
|
if (mTargetDragData) {
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG, ("dataFound = PR_TRUE\n"));
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
+ ("dataFound = PR_TRUE for %s\n", gdk_atom_name(mTargetDragGdkAtom)));
|
|
dataFound = PR_TRUE;
|
|
- }
|
|
- else {
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG, ("dataFound = PR_FALSE\n"));
|
|
- // if we are looking for text/unicode and we fail to find it
|
|
- // on the clipboard first, try again with text/plain. If that
|
|
- // is present, convert it to unicode.
|
|
- if ( strcmp(flavorStr, kUnicodeMime) == 0 ) {
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("we were looking for text/unicode... \
|
|
- trying again with text/plain\n"));
|
|
- gdkFlavor = gdk_atom_intern(kTextMime, FALSE);
|
|
- GetTargetDragData(gdkFlavor);
|
|
- if (mTargetDragData) {
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG, ("Got textplain data\n"));
|
|
- const char* castedText =
|
|
- NS_REINTERPRET_CAST(char*, mTargetDragData);
|
|
- PRUnichar* convertedText = nsnull;
|
|
- PRInt32 convertedTextLen = 0;
|
|
- nsPrimitiveHelpers::ConvertPlatformPlainTextToUnicode(
|
|
- castedText, mTargetDragDataLen,
|
|
- &convertedText, &convertedTextLen);
|
|
- if ( convertedText ) {
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("successfully converted plain text \
|
|
- to unicode.\n"));
|
|
- // out with the old, in with the new
|
|
- g_free(mTargetDragData);
|
|
- mTargetDragData = convertedText;
|
|
- mTargetDragDataLen = convertedTextLen * 2;
|
|
- dataFound = PR_TRUE;
|
|
- } // if plain text data on clipboard
|
|
- } // if plain text flavor present
|
|
- } // if looking for text/unicode
|
|
-
|
|
- // if we are looking for text/x-moz-url and we failed to find
|
|
- // it on the clipboard, try again with text/uri-list, and then
|
|
- // _NETSCAPE_URL
|
|
- if (strcmp(flavorStr, kURLMime) == 0) {
|
|
+
|
|
+ // we need to do extra work for text/uri-list
|
|
+ if (mTargetDragGdkAtom ==
|
|
+ gdk_atom_intern(gTextUriListType, FALSE)) {
|
|
PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("we were looking for text/x-moz-url...\
|
|
- trying again with text/uri-list\n"));
|
|
- gdkFlavor = gdk_atom_intern(gTextUriListType, FALSE);
|
|
- GetTargetDragData(gdkFlavor);
|
|
- if (mTargetDragData) {
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("Got text/uri-list data\n"));
|
|
- const char *data =
|
|
- NS_REINTERPRET_CAST(char*, mTargetDragData);
|
|
- PRUnichar* convertedText = nsnull;
|
|
- PRInt32 convertedTextLen = 0;
|
|
+ ("Converting text/uri-list data\n"));
|
|
+ const char *data =
|
|
+ NS_REINTERPRET_CAST(char*, mTargetDragData);
|
|
+ PRUnichar* convertedText = nsnull;
|
|
+ PRInt32 convertedTextLen = 0;
|
|
|
|
- GetTextUriListItem(data, mTargetDragDataLen, aItemIndex,
|
|
- &convertedText, &convertedTextLen);
|
|
+ GetTextUriListItem(data, mTargetDragDataLen, aItemIndex,
|
|
+ &convertedText, &convertedTextLen);
|
|
|
|
- if ( convertedText ) {
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("successfully converted \
|
|
- _NETSCAPE_URL to unicode.\n"));
|
|
- // out with the old, in with the new
|
|
- g_free(mTargetDragData);
|
|
- mTargetDragData = convertedText;
|
|
- mTargetDragDataLen = convertedTextLen * 2;
|
|
- dataFound = PR_TRUE;
|
|
- }
|
|
- }
|
|
- else {
|
|
+ if (convertedText) {
|
|
PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("failed to get text/uri-list data\n"));
|
|
+ ("successfully converted \
|
|
+ %s to unicode.\n", gTextUriListType));
|
|
+ // out with the old, in with the new
|
|
+ g_free(mTargetDragData);
|
|
+ mTargetDragData = convertedText;
|
|
+ mTargetDragDataLen = convertedTextLen * 2;
|
|
}
|
|
- if (!dataFound) {
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("we were looking for text/x-moz-url...\
|
|
- trying again with _NETSCAP_URL\n"));
|
|
- gdkFlavor = gdk_atom_intern(gMozUrlType, FALSE);
|
|
- GetTargetDragData(gdkFlavor);
|
|
- if (mTargetDragData) {
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("Got _NETSCAPE_URL data\n"));
|
|
- const char* castedText =
|
|
- NS_REINTERPRET_CAST(char*, mTargetDragData);
|
|
- PRUnichar* convertedText = nsnull;
|
|
- PRInt32 convertedTextLen = 0;
|
|
- nsPrimitiveHelpers::ConvertPlatformPlainTextToUnicode(castedText, mTargetDragDataLen, &convertedText, &convertedTextLen);
|
|
- if ( convertedText ) {
|
|
- PR_LOG(sDragLm,
|
|
- PR_LOG_DEBUG,
|
|
- ("successfully converted _NETSCAPE_URL \
|
|
- to unicode.\n"));
|
|
- // out with the old, in with the new
|
|
- g_free(mTargetDragData);
|
|
- mTargetDragData = convertedText;
|
|
- mTargetDragDataLen = convertedTextLen * 2;
|
|
- dataFound = PR_TRUE;
|
|
- }
|
|
- }
|
|
- else {
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("failed to get _NETSCAPE_URL data\n"));
|
|
- }
|
|
- }
|
|
}
|
|
-
|
|
- } // else we try one last ditch effort to find our data
|
|
-
|
|
+ // Convert text/html into our unicode format
|
|
+ else if (mTargetDragGdkAtom ==
|
|
+ gdk_atom_intern(kHTMLMime, FALSE)) {
|
|
+ PRUnichar* htmlBody= nsnull;
|
|
+ PRInt32 htmlBodyLen = 0;
|
|
+
|
|
+ ConvertHTMLtoUCS2(NS_STATIC_CAST(guchar*, mTargetDragData),
|
|
+ mTargetDragDataLen,
|
|
+ &htmlBody, htmlBodyLen);
|
|
+ if (!htmlBodyLen)
|
|
+ break;
|
|
+ g_free(mTargetDragData);
|
|
+ mTargetDragData = (void *)htmlBody;
|
|
+ mTargetDragDataLen = htmlBodyLen * 2;
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG, ("dataFound = PR_FALSE\n"));
|
|
+ }
|
|
if (dataFound) {
|
|
// the DOM only wants LF, so convert from MacOS line endings
|
|
// to DOM line endings.
|
|
@@ -542,7 +537,7 @@
|
|
nsDragService::IsDataFlavorSupported(const char *aDataFlavor,
|
|
PRBool *_retval)
|
|
{
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::IsDataFlavorSupported %s",
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::IsDataFlavorSupported %s\n",
|
|
aDataFlavor));
|
|
if (!_retval)
|
|
return NS_ERROR_INVALID_ARG;
|
|
@@ -595,7 +590,7 @@
|
|
currentFlavor->ToString(getter_Copies(flavorStr));
|
|
PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
("checking %s against %s\n",
|
|
- (const char *)flavorStr, aDataFlavor));
|
|
+ (const char *)flavorStr, aDataFlavor));
|
|
if (strcmp(flavorStr, aDataFlavor) == 0) {
|
|
PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
("boioioioiooioioioing!\n"));
|
|
@@ -609,50 +604,9 @@
|
|
return NS_OK;
|
|
}
|
|
|
|
- // check the target context vs. this flavor, one at a time
|
|
- GList *tmp;
|
|
- for (tmp = mTargetDragContext->targets; tmp; tmp = tmp->next) {
|
|
- GdkAtom atom = (GdkAtom)GPOINTER_TO_INT(tmp->data);
|
|
- gchar *name = NULL;
|
|
- name = gdk_atom_name(atom);
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("checking %s against %s\n", name, aDataFlavor));
|
|
- if (name && (strcmp(name, aDataFlavor) == 0)) {
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG, ("good!\n"));
|
|
- *_retval = PR_TRUE;
|
|
- }
|
|
- // check for automatic text/uri-list -> text/x-moz-url mapping
|
|
- if (*_retval == PR_FALSE &&
|
|
- name &&
|
|
- (strcmp(name, gTextUriListType) == 0) &&
|
|
- (strcmp(aDataFlavor, kURLMime) == 0)) {
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("good! ( it's text/uri-list and \
|
|
- we're checking against text/x-moz-url )\n"));
|
|
- *_retval = PR_TRUE;
|
|
- }
|
|
- // check for automatic _NETSCAPE_URL -> text/x-moz-url mapping
|
|
- if (*_retval == PR_FALSE &&
|
|
- name &&
|
|
- (strcmp(name, gMozUrlType) == 0) &&
|
|
- (strcmp(aDataFlavor, kURLMime) == 0)) {
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("good! ( it's _NETSCAPE_URL and \
|
|
- we're checking against text/x-moz-url )\n"));
|
|
- *_retval = PR_TRUE;
|
|
- }
|
|
- // check for auto text/plain -> text/unicode mapping
|
|
- if (*_retval == PR_FALSE &&
|
|
- name &&
|
|
- (strcmp(name, kTextMime) == 0) &&
|
|
- (strcmp(aDataFlavor, kUnicodeMime) == 0)) {
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("good! ( it's text plain and we're checking \
|
|
- against text/unicode )\n"));
|
|
- *_retval = PR_TRUE;
|
|
- }
|
|
- g_free(name);
|
|
- }
|
|
+ if (LookupFlavorInTargetList(aDataFlavor) ||
|
|
+ LookupMatchedOutsideTarget(aDataFlavor, NULL, NULL))
|
|
+ *_retval = PR_TRUE;
|
|
return NS_OK;
|
|
}
|
|
|
|
@@ -691,14 +645,14 @@
|
|
// notify the dragger if we can drop
|
|
switch (mDragAction) {
|
|
case DRAGDROP_ACTION_COPY:
|
|
- action = GDK_ACTION_COPY;
|
|
- break;
|
|
+ action = GDK_ACTION_COPY;
|
|
+ break;
|
|
case DRAGDROP_ACTION_LINK:
|
|
- action = GDK_ACTION_LINK;
|
|
- break;
|
|
+ action = GDK_ACTION_LINK;
|
|
+ break;
|
|
default:
|
|
- action = GDK_ACTION_MOVE;
|
|
- break;
|
|
+ action = GDK_ACTION_MOVE;
|
|
+ break;
|
|
}
|
|
gdk_drag_status(aContext, action, aTime);
|
|
}
|
|
@@ -719,12 +673,23 @@
|
|
guint32 aTime)
|
|
{
|
|
PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::TargetDataReceived"));
|
|
- TargetResetData();
|
|
+ NS_ASSERTION(mTargetDragData == 0, "Data area is NOT empty!!\n");
|
|
+ NS_ASSERTION(mTargetDragDataLen == 0, "Data area is NOT empty!!\n");
|
|
+
|
|
mTargetDragDataReceived = PR_TRUE;
|
|
if (aSelectionData->length > 0) {
|
|
- mTargetDragDataLen = aSelectionData->length;
|
|
- mTargetDragData = g_malloc(mTargetDragDataLen);
|
|
- memcpy(mTargetDragData, aSelectionData->data, mTargetDragDataLen);
|
|
+ if (mTargetDragGdkAtom && mTargetConverter) {
|
|
+ // need Converting
|
|
+ (*mTargetConverter)((const char*)aSelectionData->data,
|
|
+ aSelectionData->length,
|
|
+ (char **)&mTargetDragData,
|
|
+ &mTargetDragDataLen);
|
|
+ }
|
|
+ else {
|
|
+ mTargetDragDataLen = aSelectionData->length;
|
|
+ mTargetDragData = g_malloc(mTargetDragDataLen);
|
|
+ memcpy(mTargetDragData, aSelectionData->data, mTargetDragDataLen);
|
|
+ }
|
|
}
|
|
else {
|
|
PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
@@ -781,13 +746,31 @@
|
|
void
|
|
nsDragService::GetTargetDragData(GdkAtom aFlavor)
|
|
{
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG, ("getting data flavor %d\n", aFlavor));
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG, ("mLastWidget is %p and mLastContext is %p\n",
|
|
- mTargetWidget, mTargetDragContext));
|
|
+ const char *flavorStr = gdk_atom_name(aFlavor);
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG, ("GetTargetData with flavor %s\n", flavorStr));
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
+ ("mLastWidget is %p, mLastContext is %p\n",
|
|
+ (void*)mTargetWidget, (void*)mTargetDragContext));
|
|
// reset our target data areas
|
|
TargetResetData();
|
|
- gtk_drag_get_data(mTargetWidget, mTargetDragContext, aFlavor, mTargetTime);
|
|
-
|
|
+ // if it is a direct match
|
|
+ if (LookupFlavorInTargetList(flavorStr)) {
|
|
+ gtk_drag_get_data(mTargetWidget, mTargetDragContext,
|
|
+ aFlavor, mTargetTime);
|
|
+ mTargetDragGdkAtom = aFlavor;
|
|
+
|
|
+ }
|
|
+ // if it is a auto converting match
|
|
+ else if (LookupMatchedOutsideTarget(flavorStr,
|
|
+ &mTargetDragGdkAtom,
|
|
+ &mTargetConverter))
|
|
+ gtk_drag_get_data(mTargetWidget, mTargetDragContext,
|
|
+ mTargetDragGdkAtom, mTargetTime);
|
|
+ else {
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG, ("Cannot request target %s\n",
|
|
+ flavorStr));
|
|
+ return;
|
|
+ }
|
|
PR_LOG(sDragLm, PR_LOG_DEBUG, ("about to start inner iteration."));
|
|
PRTime entryTime = PR_Now();
|
|
while (!mTargetDragDataReceived && mDoingDrag) {
|
|
@@ -807,9 +791,11 @@
|
|
mTargetDragDataReceived = PR_FALSE;
|
|
// make sure to free old data if we have to
|
|
if (mTargetDragData)
|
|
- g_free(mTargetDragData);
|
|
+ g_free(mTargetDragData);
|
|
mTargetDragData = 0;
|
|
mTargetDragDataLen = 0;
|
|
+ mTargetDragGdkAtom = 0;
|
|
+ mTargetConverter = NULL;
|
|
}
|
|
|
|
GtkTargetList *
|
|
@@ -841,7 +827,7 @@
|
|
listTarget->info = (guint)listAtom;
|
|
PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
("automatically adding target %s with id %ld\n",
|
|
- listTarget->target, listAtom));
|
|
+ listTarget->target, listAtom));
|
|
targetArray.AppendElement(listTarget);
|
|
|
|
// check what flavours are supported so we can decide what other
|
|
@@ -861,7 +847,7 @@
|
|
++flavorIndex ) {
|
|
nsCOMPtr<nsISupports> genericWrapper;
|
|
flavorList->GetElementAt(flavorIndex,
|
|
- getter_AddRefs(genericWrapper));
|
|
+ getter_AddRefs(genericWrapper));
|
|
nsCOMPtr<nsISupportsCString> currentFlavor;
|
|
currentFlavor = do_QueryInterface(genericWrapper);
|
|
if (currentFlavor) {
|
|
@@ -908,51 +894,27 @@
|
|
if (currentFlavor) {
|
|
nsXPIDLCString flavorStr;
|
|
currentFlavor->ToString(getter_Copies(flavorStr));
|
|
- // get the atom
|
|
- GdkAtom atom = gdk_atom_intern(flavorStr, FALSE);
|
|
- GtkTargetEntry *target =
|
|
- (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
|
|
- target->target = g_strdup(flavorStr);
|
|
- target->flags = 0;
|
|
- target->info = GPOINTER_TO_UINT(atom);
|
|
+ //add the target itself
|
|
+ GtkTargetEntry *target = CreateGtkTargetFor(flavorStr);
|
|
PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("adding target %s with id %ld\n",
|
|
- target->target, atom));
|
|
+ ("+++adding importable target %s\n",
|
|
+ target->target));
|
|
targetArray.AppendElement(target);
|
|
- // Check to see if this is text/unicode.
|
|
- // If it is, add text/plain
|
|
- // since we automatically support text/plain
|
|
- // if we support text/unicode.
|
|
- if (strcmp(flavorStr, kUnicodeMime) == 0) {
|
|
- // get the atom for the unicode string
|
|
- GdkAtom plainAtom =
|
|
- gdk_atom_intern(kTextMime, FALSE);
|
|
- GtkTargetEntry *plainTarget =
|
|
- (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
|
|
- plainTarget->target = g_strdup(kTextMime);
|
|
- plainTarget->flags = 0;
|
|
- plainTarget->info = GPOINTER_TO_UINT(plainAtom);
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("automatically adding target %s with \
|
|
- id %ld\n", plainTarget->target, plainAtom));
|
|
- targetArray.AppendElement(plainTarget);
|
|
- }
|
|
- // Check to see if this is the x-moz-url type.
|
|
- // If it is, add _NETSCAPE_URL
|
|
- // this is a type used by everybody.
|
|
- if (strcmp(flavorStr, kURLMime) == 0) {
|
|
- // get the atom name for it
|
|
- GdkAtom urlAtom =
|
|
- gdk_atom_intern(gMozUrlType, FALSE);
|
|
- GtkTargetEntry *urlTarget =
|
|
- (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
|
|
- urlTarget->target = g_strdup(gMozUrlType);
|
|
- urlTarget->flags = 0;
|
|
- urlTarget->info = GPOINTER_TO_UINT(urlAtom);
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
- ("automatically adding target %s with \
|
|
- id %ld\n", urlTarget->target, urlAtom));
|
|
- targetArray.AppendElement(urlTarget);
|
|
+
|
|
+ //add the auto convert targets
|
|
+ PRUint16 convIndex = 0;
|
|
+ while (autoConvertPair[convIndex].internal &&
|
|
+ autoConvertPair[convIndex].outside) {
|
|
+ if (!strcmp(autoConvertPair[convIndex].internal,
|
|
+ flavorStr)) {
|
|
+ target = CreateGtkTargetFor( \
|
|
+ autoConvertPair[convIndex].outside);
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
+ (" ++auto adding target %s\n",
|
|
+ target->target));
|
|
+ targetArray.AppendElement(target);
|
|
+ }
|
|
+ ++convIndex;
|
|
}
|
|
}
|
|
} // foreach flavor in item
|
|
@@ -965,11 +927,11 @@
|
|
if (targetCount) {
|
|
// allocate space to create the list of valid targets
|
|
targets =
|
|
- (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry) * targetCount);
|
|
+ (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry) * targetCount);
|
|
PRUint32 targetIndex;
|
|
for ( targetIndex = 0; targetIndex < targetCount; ++targetIndex) {
|
|
GtkTargetEntry *disEntry =
|
|
- (GtkTargetEntry *)targetArray.ElementAt(targetIndex);
|
|
+ (GtkTargetEntry *)targetArray.ElementAt(targetIndex);
|
|
// this is a string reference but it will be freed later.
|
|
targets[targetIndex].target = disEntry->target;
|
|
targets[targetIndex].flags = disEntry->flags;
|
|
@@ -979,7 +941,7 @@
|
|
// clean up the target list
|
|
for (PRUint32 cleanIndex = 0; cleanIndex < targetCount; ++cleanIndex) {
|
|
GtkTargetEntry *thisTarget =
|
|
- (GtkTargetEntry *)targetArray.ElementAt(cleanIndex);
|
|
+ (GtkTargetEntry *)targetArray.ElementAt(cleanIndex);
|
|
g_free(thisTarget->target);
|
|
g_free(thisTarget);
|
|
}
|
|
@@ -1067,7 +1029,7 @@
|
|
guint aInfo,
|
|
guint32 aTime)
|
|
{
|
|
- PR_LOG(sDragLm, PR_LOG_DEBUG, ("nsDragService::SourceDataGet"));
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG, ("\nnsDragService::SourceDataGet"));
|
|
GdkAtom atom = (GdkAtom)aInfo;
|
|
nsXPIDLCString mimeFlavor;
|
|
gchar *typeName = 0;
|
|
@@ -1104,22 +1066,18 @@
|
|
nsCOMPtr<nsITransferable> item;
|
|
item = do_QueryInterface(genericItem);
|
|
if (item) {
|
|
- // if someone was asking for text/plain, lookup unicode instead so
|
|
- // we can convert it.
|
|
- PRBool needToDoConversionToPlainText = PR_FALSE;
|
|
+ TargetConverter converter = NULL;
|
|
const char* actualFlavor = mimeFlavor;
|
|
- if (strcmp(mimeFlavor,kTextMime) == 0) {
|
|
- actualFlavor = kUnicodeMime;
|
|
- needToDoConversionToPlainText = PR_TRUE;
|
|
- }
|
|
- // if someone was asking for _NETSCAPE_URL we need to convert to
|
|
- // plain text but we also need to look for x-moz-url
|
|
- else if (strcmp(mimeFlavor, gMozUrlType) == 0) {
|
|
- actualFlavor = kURLMime;
|
|
- needToDoConversionToPlainText = PR_TRUE;
|
|
+ PRUint32 convIndex = 0;
|
|
+ while (autoConvertPair[convIndex].outside &&
|
|
+ autoConvertPair[convIndex].internal) {
|
|
+ if (!strcmp(mimeFlavor, autoConvertPair[convIndex].outside)) {
|
|
+ actualFlavor = autoConvertPair[convIndex].internal;
|
|
+ converter = autoConvertPair[convIndex].in2out;
|
|
+ break;
|
|
+ }
|
|
+ ++convIndex;
|
|
}
|
|
- else
|
|
- actualFlavor = mimeFlavor;
|
|
|
|
PRUint32 tmpDataLen = 0;
|
|
void *tmpData = NULL;
|
|
@@ -1131,18 +1089,24 @@
|
|
if (NS_SUCCEEDED(rv)) {
|
|
nsPrimitiveHelpers::CreateDataFromPrimitive (actualFlavor, data,
|
|
&tmpData, tmpDataLen);
|
|
+
|
|
+ if (strcmp(actualFlavor, kHTMLMime) == 0) {
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG, ("add BOM prefix for %s\n",
|
|
+ kHTMLMime));
|
|
+ addBOM(NS_REINTERPRET_CAST(guchar **, &tmpData),
|
|
+ NS_REINTERPRET_CAST(gint *, &tmpDataLen));
|
|
+ }
|
|
+
|
|
// if required, do the extra work to convert unicode to plain
|
|
// text and replace the output values with the plain text.
|
|
- if (needToDoConversionToPlainText) {
|
|
+ if (converter) {
|
|
char* plainTextData = nsnull;
|
|
PRUnichar* castedUnicode = NS_REINTERPRET_CAST(PRUnichar*,
|
|
tmpData);
|
|
- PRInt32 plainTextLen = 0;
|
|
- nsPrimitiveHelpers::ConvertUnicodeToPlatformPlainText(
|
|
- castedUnicode,
|
|
- tmpDataLen / 2,
|
|
- &plainTextData,
|
|
- &plainTextLen);
|
|
+ PRUint32 plainTextLen = 0;
|
|
+ (*converter)((const char*)castedUnicode, tmpDataLen,
|
|
+ &plainTextData, &plainTextLen);
|
|
+
|
|
if (tmpData) {
|
|
// this was not allocated using glib
|
|
free(tmpData);
|
|
@@ -1190,3 +1154,149 @@
|
|
dragService->SourceEndDrag();
|
|
}
|
|
|
|
+PRBool
|
|
+nsDragService::LookupFlavorInTargetList(const char *aDataFlavor)
|
|
+{
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
+ ("nsDragService::LookupFlavorInTargetList,"
|
|
+ "checking %s \n", aDataFlavor));
|
|
+
|
|
+ if (!mTargetDragContext || !aDataFlavor)
|
|
+ return PR_FALSE;
|
|
+
|
|
+ GList *targetList = mTargetDragContext->targets;
|
|
+ while (targetList) {
|
|
+ GdkAtom atom = (GdkAtom)GPOINTER_TO_INT(targetList->data);
|
|
+ gchar *atomName = gdk_atom_name(atom);
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
+ ("checking %s against %s\n", aDataFlavor, atomName));
|
|
+ if (atomName && (strcmp(atomName, aDataFlavor) == 0)) {
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG, ("good!\n"));
|
|
+ g_free(atomName);
|
|
+ return PR_TRUE;
|
|
+ }
|
|
+ targetList = targetList->next;
|
|
+ }
|
|
+ return PR_FALSE;
|
|
+}
|
|
+
|
|
+PRBool
|
|
+nsDragService::LookupMatchedOutsideTarget(const char *aDataFlavor,
|
|
+ GdkAtom *aAtom,
|
|
+ TargetConverter *aConverter)
|
|
+{
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
+ ("nsDragService::LookupMatchedOutsideTarget,"
|
|
+ "checking %s \n", aDataFlavor));
|
|
+
|
|
+ if (!mTargetDragContext || !aDataFlavor)
|
|
+ return PR_FALSE;
|
|
+
|
|
+ gint index = 0;
|
|
+ while (autoConvertPair[index].internal &&
|
|
+ autoConvertPair[index].outside) {
|
|
+ if (!strcmp(autoConvertPair[index].internal, aDataFlavor) &&
|
|
+ LookupFlavorInTargetList(autoConvertPair[index].outside)) {
|
|
+ if (aConverter)
|
|
+ *aConverter = autoConvertPair[index].out2in;
|
|
+ if (aAtom)
|
|
+ *aAtom = gdk_atom_intern(autoConvertPair[index].outside,
|
|
+ FALSE);
|
|
+ return PR_TRUE;
|
|
+ }
|
|
+ ++index;
|
|
+ }
|
|
+ return PR_FALSE;
|
|
+}
|
|
+
|
|
+PRBool
|
|
+nsDragService::LookupMatchedInternalTarget(const char *aDataFlavor,
|
|
+ GdkAtom *aAtom,
|
|
+ TargetConverter *aConverter)
|
|
+{
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
+ ("nsDragService::LookupMatchedInternalTarget,"
|
|
+ "checking %s \n", aDataFlavor));
|
|
+
|
|
+ if (!mTargetDragContext || !aDataFlavor)
|
|
+ return PR_FALSE;
|
|
+
|
|
+ gint index = 0;
|
|
+ while (autoConvertPair[index].internal &&
|
|
+ autoConvertPair[index].outside) {
|
|
+ if (!strcmp(autoConvertPair[index].outside, aDataFlavor) &&
|
|
+ LookupFlavorInTargetList(autoConvertPair[index].internal)) {
|
|
+ if (aConverter)
|
|
+ *aConverter = autoConvertPair[index].in2out;
|
|
+ if (aAtom)
|
|
+ *aAtom = gdk_atom_intern(autoConvertPair[index].internal,
|
|
+ FALSE);
|
|
+ return PR_TRUE;
|
|
+ }
|
|
+ ++index;
|
|
+ }
|
|
+ return PR_FALSE;
|
|
+}
|
|
+
|
|
+GtkTargetEntry *
|
|
+nsDragService::CreateGtkTargetFor(const char *aFlavorStr)
|
|
+{
|
|
+ // get the atom
|
|
+ GdkAtom atom = gdk_atom_intern(aFlavorStr, FALSE);
|
|
+ GtkTargetEntry *target =
|
|
+ (GtkTargetEntry *)g_malloc(sizeof(GtkTargetEntry));
|
|
+ NS_ASSERTION(target, "No enough mem");
|
|
+
|
|
+ target->target = g_strdup(aFlavorStr);
|
|
+ target->flags = 0;
|
|
+ target->info = GPOINTER_TO_UINT(atom);
|
|
+
|
|
+ return target;
|
|
+}
|
|
+
|
|
+//converters
|
|
+
|
|
+// static
|
|
+void
|
|
+utf8_to_ucs2 (const char *aDataIn, unsigned int aDataInLen,
|
|
+ char **aDataOut, unsigned int *aDataOutLen)
|
|
+{
|
|
+ nsAutoString ucs2string = NS_ConvertUTF8toUCS2(aDataIn);
|
|
+ *aDataOut = (char *)ToNewUnicode(ucs2string);
|
|
+ *aDataOutLen = ucs2string.Length() * 2;
|
|
+
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
+ ("AutoConverting: utf8 ---> unicode.\n"));
|
|
+
|
|
+}
|
|
+
|
|
+//static
|
|
+void
|
|
+ucs2_to_text (const char *aDataIn, unsigned int aDataInLen,
|
|
+ char **aDataOut, unsigned int *aDataOutLen)
|
|
+{
|
|
+ nsPrimitiveHelpers::
|
|
+ ConvertUnicodeToPlatformPlainText((PRUnichar *)aDataIn,
|
|
+ int(aDataInLen / 2),
|
|
+ aDataOut, (PRInt32 *)aDataOutLen);
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
+ ("AutoConverting: ucs2 ---> platform text.\n"));
|
|
+}
|
|
+
|
|
+//static
|
|
+void
|
|
+text_to_ucs2 (const char *aDataIn, unsigned int aDataInLen,
|
|
+ char **aDataOut, unsigned int *aDataOutLen)
|
|
+{
|
|
+ PRUnichar *convertedText = nsnull;
|
|
+ PRInt32 convertedTextLen = 0;
|
|
+ nsPrimitiveHelpers::
|
|
+ ConvertPlatformPlainTextToUnicode(aDataIn, aDataInLen,
|
|
+ &convertedText, &convertedTextLen);
|
|
+ if (convertedText) {
|
|
+ PR_LOG(sDragLm, PR_LOG_DEBUG,
|
|
+ ("AutoConverting: plain text ---> unicode.\n"));
|
|
+ *aDataOut = NS_REINTERPRET_CAST(char*, convertedText);
|
|
+ *aDataOutLen = convertedTextLen * 2;
|
|
+ }
|
|
+}
|
|
Index: widget/src/gtk2/nsDragService.h
|
|
===================================================================
|
|
RCS file: /export/src/cvs/mozilla1.7/mozilla/widget/src/gtk2/nsDragService.h,v
|
|
retrieving revision 1.1.1.1
|
|
diff -u -r1.1.1.1 nsDragService.h
|
|
--- widget/src/gtk2/nsDragService.h 2004/04/13 06:46:17 1.1.1.1
|
|
+++ widget/src/gtk2/nsDragService.h 2004/04/13 08:22:00
|
|
@@ -33,6 +33,8 @@
|
|
#include "nsIObserver.h"
|
|
#include <gtk/gtk.h>
|
|
|
|
+typedef void (*TargetConverter) (const char *aDataIn, unsigned int aDataInLen,
|
|
+ char **aDataOut, unsigned int *aDataOutLen);
|
|
|
|
/**
|
|
* Native GTK DragService wrapper
|
|
@@ -64,7 +66,8 @@
|
|
NS_IMETHOD GetNumDropItems (PRUint32 * aNumItems);
|
|
NS_IMETHOD GetData (nsITransferable * aTransferable,
|
|
PRUint32 aItemIndex);
|
|
- NS_IMETHOD IsDataFlavorSupported (const char *aDataFlavor, PRBool *_retval);
|
|
+ NS_IMETHOD IsDataFlavorSupported (const char *aDataFlavor,
|
|
+ PRBool *_retval);
|
|
|
|
// nsIDragSessionGTK
|
|
|
|
@@ -112,6 +115,9 @@
|
|
// last data received and its length
|
|
void *mTargetDragData;
|
|
PRUint32 mTargetDragDataLen;
|
|
+ GdkAtom mTargetDragGdkAtom; // the real target we asked for
|
|
+ TargetConverter mTargetConverter; //
|
|
+
|
|
// is the current target drag context contain a list?
|
|
PRBool IsTargetContextList(void);
|
|
// this will get the native data from the last target given a
|
|
@@ -129,7 +135,17 @@
|
|
// get a list of the sources in gtk's format
|
|
GtkTargetList *GetSourceList(void);
|
|
|
|
+ // check if a flavor supported by source target list
|
|
+ PRBool LookupFlavorInTargetList(const char *aDataFlavor);
|
|
+ PRBool LookupMatchedOutsideTarget(const char *aDataFlavor,
|
|
+ GdkAtom *aAtom,
|
|
+ TargetConverter *aConverter);
|
|
+ PRBool LookupMatchedInternalTarget(const char *aDataFlavor,
|
|
+ GdkAtom *aAtom,
|
|
+ TargetConverter *aConverter);
|
|
+
|
|
+ GtkTargetEntry *CreateGtkTargetFor(const char *aFlavorStr);
|
|
+
|
|
};
|
|
|
|
#endif // nsDragService_h__
|
|
-
|