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 #include #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 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 genericWrapper; flavorList->GetElementAt(flavorIndex, - getter_AddRefs(genericWrapper)); + getter_AddRefs(genericWrapper)); nsCOMPtr 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 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 +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__ -