Revision: 25412
          http://sourceforge.net/p/bibdesk/svn/25412
Author:   hofman
Date:     2021-01-16 15:40:15 +0000 (Sat, 16 Jan 2021)
Log Message:
-----------
Use cocoa to read and write URLs on pasteboard

Modified Paths:
--------------
    trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m
    trunk/bibdesk_vendorsrc/amaxwell/FileView/FVUtilities.h
    trunk/bibdesk_vendorsrc/amaxwell/FileView/FVUtilities.m

Modified: trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m
===================================================================
--- trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m      2021-01-16 
15:23:26 UTC (rev 25411)
+++ trunk/bibdesk_vendorsrc/amaxwell/FileView/FVFileView.m      2021-01-16 
15:40:15 UTC (rev 25412)
@@ -2722,7 +2722,8 @@
 - (void)dragSelectionForEvent:(NSEvent *)event;
 {
     NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
-    if (FVWriteURLsToPasteboard([self _selectedURLs], pboard) == NO)
+    [pboard clearContents];
+    if (NO == [pboard writeObjects:[self _selectedURLs]])
         return;
     
     NSUInteger r, c, cMin = NSUIntegerMax, cMax = 0, rMin = NSUIntegerMax, 
rMax = 0;
@@ -2797,7 +2798,7 @@
     NSUInteger insertIndex, firstIndex, endIndex;
     
     // !!! this is quite expensive to call repeatedly in -draggingUpdated
-    BOOL hasURLs = FVPasteboardHasURL([sender draggingPasteboard]);
+    BOOL hasURLs = [[sender draggingPasteboard] 
canReadObjectForClasses:[NSArray arrayWithObject:[NSURL class]] options:nil];
     
     // First determine the drop location, drop between rows in column mode, 
and between columns otherwise
     if (_fvFlags.displayMode == FVDisplayModeColumn)
@@ -2900,7 +2901,7 @@
     BOOL isCopy = [self allowsDownloading] && dragOp == NSDragOperationCopy;
     BOOL isMove = [self _isLocalDraggingInfo:sender] && isCopy == NO;
     BOOL didPerform = NO;
-    NSArray *draggedURLs = isMove ? nil : FVURLsFromPasteboard(pboard);
+    NSArray *draggedURLs = isMove ? nil : [pboard 
readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]] options:nil];
     NSArray *allURLs = draggedURLs;
     NSMutableArray *downloads = nil;
     NSUInteger insertIndex = 0;
@@ -3804,7 +3805,9 @@
 
 - (IBAction)copy:(id)sender;
 {
-    if (NO == FVWriteURLsToPasteboard([self _selectedURLs], [NSPasteboard 
generalPasteboard]))
+    NSPasteboard *pboard = [NSPasteboard generalPasteboard];
+    [pboard clearContents];
+    if (NO == [pboard writeObjects:[self _selectedURLs]])
         NSBeep();
 }
 
@@ -3817,7 +3820,7 @@
 - (IBAction)paste:(id)sender;
 {
     if ([self isEditable]) {
-        NSArray *URLs = FVURLsFromPasteboard([NSPasteboard generalPasteboard]);
+        NSArray *URLs = [[NSPasteboard generalPasteboard] 
readObjectsForClasses:[NSArray arrayWithObject:[NSURL class]] options:nil];
         if ([URLs count])
             [[self dataSource] fileView:self insertURLs:URLs 
atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange([self 
numberOfIcons], [URLs count])] forDrop:nil dropOperation:FVDropOn];
         else

Modified: trunk/bibdesk_vendorsrc/amaxwell/FileView/FVUtilities.h
===================================================================
--- trunk/bibdesk_vendorsrc/amaxwell/FileView/FVUtilities.h     2021-01-16 
15:23:26 UTC (rev 25411)
+++ trunk/bibdesk_vendorsrc/amaxwell/FileView/FVUtilities.h     2021-01-16 
15:40:15 UTC (rev 25412)
@@ -61,25 +61,6 @@
 FV_PRIVATE_EXTERN void FVLog(NSString *format, ...);
 
 /** @internal
- Checks the pasteboard for any URL data.  Converts an NSPasteboard to a Carbon 
PasteboardRef. 
- @param pboard Any NSPasteboard instance.
- @return YES if pboard has a URL type or a string that can be converted to a 
URL. */
-FV_PRIVATE_EXTERN BOOL FVPasteboardHasURL(NSPasteboard *pboard);
-
-/** @internal
- Reads URLs from the pasteboard, whether file: or other scheme.  Finder puts 
multiple URLs on the pasteboard, and also webloc files.  Converts an 
NSPasteboard to a Carbon PasteboardRef in order to work around NSPasteboard's 
terrible URL support.
- @param pboard Any NSPasteboard instance.
- @return An array of URLs from the pasteboard. */
-FV_PRIVATE_EXTERN NSArray *FVURLsFromPasteboard(NSPasteboard *pboard);
-
-/** @internal
- Writes URLs to the pasteboard as UTF-8 data.  Converts an NSPasteboard to a 
Carbon PasteboardRef in order to work around NSPasteboard's terrible URL 
support.
- @param URLs An array of URLs to write to the pasteboard.
- @param pboard Any NSPasteboard instance.
- @return YES if all URLs were written successfully. */
-FV_PRIVATE_EXTERN BOOL FVWriteURLsToPasteboard(NSArray *URLs, NSPasteboard 
*pboard);
-
-/** @internal
  Creates an NSGraphicsContext using an NSWindow as backing.  Intended for use 
in +initialize when +[NSGraphicsContext currentContext] may be nil.
  @param size Size of the window to create.
  @return A new, autoreleased instance of NSGraphicsContext. */

Modified: trunk/bibdesk_vendorsrc/amaxwell/FileView/FVUtilities.m
===================================================================
--- trunk/bibdesk_vendorsrc/amaxwell/FileView/FVUtilities.m     2021-01-16 
15:23:26 UTC (rev 25411)
+++ trunk/bibdesk_vendorsrc/amaxwell/FileView/FVUtilities.m     2021-01-16 
15:40:15 UTC (rev 25412)
@@ -116,214 +116,8 @@
     va_end(list);
 }
 
-#pragma mark Pasteboard URL functions
+#pragma mark Graphics context
 
-BOOL FVPasteboardHasURL(NSPasteboard *pboard)
-{       
-    NSArray *types = [pboard types];
-    
-    // quicker test than URLsFromPasteboard(); at least on 10.5, NSPasteboard 
has the UTI types
-    if ([types containsObject:(id)kUTTypeURL] || [types 
containsObject:(id)kUTTypeFileURL] || [types containsObject:NSURLPboardType])
-        return YES;
-    
-    // also catches case of file URL, which conforms to kUTTypeURL, and 
strings that might be URLs
-    return [FVURLsFromPasteboard(pboard) count] > 0;
-}
-
-// NSPasteboard only lets us read a single webloc or NSURL instance from the 
pasteboard, which isn't very considerate of it.  Fortunately, we can create a 
Carbon pasteboard that isn't as fundamentally crippled (except in its 
moderately annoying API).  
-NSArray *FVURLsFromPasteboard(NSPasteboard *pboard)
-{
-    OSStatus err;
-    
-    PasteboardRef carbonPboard;
-    err = PasteboardCreate((CFStringRef)[pboard name], &carbonPboard);
-    
-    if (noErr == err)
-        (void)PasteboardSynchronize(carbonPboard);
-    
-    ItemCount itemCount, itemIndex;
-    if (noErr == err)
-        err = PasteboardGetItemCount(carbonPboard, &itemCount);
-    
-    if (noErr != err)
-        itemCount = 0;
-    
-    NSMutableArray *toReturn = [NSMutableArray arrayWithCapacity:itemCount];
-    
-    // this is to avoid duplication in the last call to NSPasteboard
-    NSMutableSet *allURLsReadFromPasteboard = [NSMutableSet 
setWithCapacity:itemCount];
-    
-    // Pasteboard has 1-based indexing!
-    
-    for (itemIndex = 1; itemIndex <= itemCount; itemIndex++) {
-        
-        PasteboardItemID itemID;
-        CFArrayRef flavors = NULL;
-        CFIndex flavorIndex, flavorCount = 0;
-        
-        err = PasteboardGetItemIdentifier(carbonPboard, itemIndex, &itemID);
-        if (noErr == err)
-            err = PasteboardCopyItemFlavors(carbonPboard, itemID, &flavors);
-        
-        if (noErr == err)
-            flavorCount = CFArrayGetCount(flavors);
-        
-        // webloc has file and non-file URL, and we may only have a string type
-        CFURLRef destURL = NULL;
-        CFURLRef fileURL = NULL;
-        CFURLRef textURL = NULL;
-        
-        // flavorCount will be zero in case of an error...
-        for (flavorIndex = 0; flavorIndex < flavorCount; flavorIndex++) {
-            
-            CFStringRef flavor;
-            CFDataRef data;
-            
-            flavor = CFArrayGetValueAtIndex(flavors, flavorIndex);
-            
-            // !!! I'm assuming that the URL bytes are UTF-8, but that should 
be checked...
-            
-            // UTIs determined with PasteboardPeeker
-            
-            /*
-             UTIs determined with PasteboardPeeker
-             Assert NULL URL on each branch; this will always be true since 
the pasteboard can only contain
-             one flavor per type.  Using UTTypeConforms instead of UTTypeEqual 
could lead to a memory
-             leak if there were multiple flavors conforming to kUTTypeURL 
(other than kUTTypeFileURL).
-             The assertion silences a clang warning.
-            */
-            if (UTTypeEqual(flavor, kUTTypeFileURL)) {
-                
-                err = PasteboardCopyItemFlavorData(carbonPboard, itemID, 
flavor, &data);
-                if (noErr == err && NULL != data) {
-                    FVAPIParameterAssert(NULL == fileURL);
-                    fileURL = CFURLCreateWithBytes(NULL, 
CFDataGetBytePtr(data), CFDataGetLength(data), kCFStringEncodingUTF8, NULL);
-                    CFRelease(data);
-                }
-                
-            } else if (UTTypeEqual(flavor, kUTTypeURL)) {
-                
-                err = PasteboardCopyItemFlavorData(carbonPboard, itemID, 
flavor, &data);
-                if (noErr == err && NULL != data) {
-                    FVAPIParameterAssert(NULL == destURL);
-                    destURL = CFURLCreateWithBytes(NULL, 
CFDataGetBytePtr(data), CFDataGetLength(data), kCFStringEncodingUTF8, NULL);
-                    CFRelease(data);
-                }
-                
-            } else if (UTTypeEqual(flavor, kUTTypeUTF8PlainText)) {
-                
-                // this is a string that may be a URL; FireFox and other apps 
don't use any of the standard URL pasteboard types
-                err = PasteboardCopyItemFlavorData(carbonPboard, itemID, 
kUTTypeUTF8PlainText, &data);
-                if (noErr == err && NULL != data) {
-                    FVAPIParameterAssert(NULL == textURL);
-                    textURL = CFURLCreateWithBytes(NULL, 
CFDataGetBytePtr(data), CFDataGetLength(data), kCFStringEncodingUTF8, NULL);
-                    CFRelease(data);
-                    
-                    // CFURLCreateWithBytes will create a URL from any 
arbitrary string
-                    if (NULL != textURL && nil == [(NSURL *)textURL scheme]) {
-                        CFRelease(textURL);
-                        textURL = NULL;
-                    }
-                }
-                
-            }
-            
-            // ignore any other type; we don't care
-            
-        }
-        
-        // only add the textURL if the destURL or fileURL were not found
-        if (NULL != textURL) {
-            if (NULL == destURL && NULL == fileURL)
-                [toReturn addObject:(id)textURL];
-            
-            [allURLsReadFromPasteboard addObject:(id)textURL];
-            CFRelease(textURL);
-        }
-        // only add the fileURL if the destURL (target of a remote URL or 
webloc) was not found
-        if (NULL != fileURL) {
-            if (NULL == destURL) 
-                [toReturn addObject:(id)fileURL];
-            
-            [allURLsReadFromPasteboard addObject:(id)fileURL];
-            CFRelease(fileURL);
-        }
-        // always add this if it exists
-        if (NULL != destURL) {
-            [toReturn addObject:(id)destURL];
-            [allURLsReadFromPasteboard addObject:(id)destURL];
-            CFRelease(destURL);
-        }
-        
-        if (NULL != flavors)
-            CFRelease(flavors);
-    }
-    
-    if (carbonPboard) CFRelease(carbonPboard);
-    
-    // NSPasteboard only allows a single NSURL for some idiotic reason, and 
NSURLPboardType isn't automagically coerced to a Carbon URL pboard type.  This 
step handles a program like BibDesk which presently adds a webloc promise + 
NSURLPboardType, where we want the NSURLPboardType data and ignore the HFS 
promise.  However, Finder puts all of these on the pboard, so don't add 
duplicate items to the array...since we may have already added the content 
(remote URL) if this is a webloc file.
-    if ([[pboard types] containsObject:NSURLPboardType]) {
-        NSURL *nsURL = [NSURL URLFromPasteboard:pboard];
-        if (nsURL && [allURLsReadFromPasteboard containsObject:nsURL] == NO)
-            [toReturn addObject:nsURL];
-    }
-    
-    // ??? On 10.5, NSStringPboardType and kUTTypeUTF8PlainText point to the 
same data, according to pasteboard peeker; if that's the case on 10.4, we can 
remove this and the registration for NSStringPboardType.
-    if ([[pboard types] containsObject:NSStringPboardType]) {
-        // this can (and does) return nil under some conditions, so avoid an 
exception
-        NSString *stringURL = [pboard stringForType:NSStringPboardType];
-        NSURL *nsURL = stringURL ? [NSURL URLWithString:stringURL] : nil;
-        if ([nsURL scheme] != nil && [allURLsReadFromPasteboard 
containsObject:nsURL] == NO)
-            [toReturn addObject:nsURL];
-    }
-    
-    return toReturn;
-}
-
-// Once we treat the NSPasteboard as a Carbon pboard, bad things seem to 
happen on Tiger (-types doesn't work), so return the PasteboardRef by reference 
to allow the caller to add more types to it or whatever.
-BOOL FVWriteURLsToPasteboard(NSArray *URLs, NSPasteboard *pboard)
-{
-    OSStatus err;
-    
-    PasteboardRef carbonPboard;
-    err = PasteboardCreate((CFStringRef)[pboard name], &carbonPboard);
-    
-    if (noErr == err)
-        err = PasteboardClear(carbonPboard);
-    
-    if (noErr == err)
-        (void)PasteboardSynchronize(carbonPboard);
-    
-    NSUInteger i, iMax = [URLs count];
-    
-    for (i = 0; i < iMax && noErr == err; i++) {
-        
-        NSURL *theURL = [URLs objectAtIndex:i];
-        NSString *string = [theURL absoluteString];
-        CFDataRef utf8Data = (CFDataRef)[string 
dataUsingEncoding:NSUTF8StringEncoding];
-        
-        // any pointer type; private to the creating application
-        PasteboardItemID itemID = (void *)theURL;
-        
-        // Finder adds a file URL and destination URL for weblocs, but only a 
file URL for regular files
-        // could also put a string representation of the URL, but Finder 
doesn't do that
-        
-        if ([theURL isFileURL]) {
-            err = PasteboardPutItemFlavor(carbonPboard, itemID, 
kUTTypeFileURL, utf8Data, kPasteboardFlavorNoFlags);
-        }
-        else {
-            err = PasteboardPutItemFlavor(carbonPboard, itemID, kUTTypeURL, 
utf8Data, kPasteboardFlavorNoFlags);
-        }
-    }
-    
-    if (carbonPboard) 
-        CFRelease(carbonPboard);
-    
-    return noErr == err;
-}
-
-#pragma mark -
-
 NSGraphicsContext *FVWindowGraphicsContextWithSize(NSSize size)
 {
     NSRect rect = NSZeroRect;
@@ -333,7 +127,7 @@
     return [NSGraphicsContext graphicsContextWithWindow:window];
 }
 
-#pragma mark -
+#pragma mark file mapping
 
 #if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MIN_REQUIRED >= 
MAC_OS_X_VERSION_10_7
 bool FVCanMapFileAtURL(NSURL *fileURL)
@@ -422,6 +216,8 @@
 }
 #endif
 
+#pragma mark Dark mode support
+
 #if !defined(MAC_OS_X_VERSION_10_9) || MAC_OS_X_VERSION_MAX_ALLOWED < 
MAC_OS_X_VERSION_10_9
 
 @interface NSAppearance : NSObject <NSCoding>

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
Bibdesk-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bibdesk-commit

Reply via email to