Revision: 25202
          http://sourceforge.net/p/bibdesk/svn/25202
Author:   hofman
Date:     2020-12-16 17:03:00 +0000 (Wed, 16 Dec 2020)
Log Message:
-----------
Use union for alias handle or bookmark data of linked file, we should only have 
one or the other

Modified Paths:
--------------
    trunk/bibdesk/BDSKLinkedFile.m

Modified: trunk/bibdesk/BDSKLinkedFile.m
===================================================================
--- trunk/bibdesk/BDSKLinkedFile.m      2020-12-16 07:30:24 UTC (rev 25201)
+++ trunk/bibdesk/BDSKLinkedFile.m      2020-12-16 17:03:00 UTC (rev 25202)
@@ -49,6 +49,7 @@
 #define ENCODED_PLIST_PREFIX @"YnBsaXN0"
 
 #define ALIASDATA_KEY @"aliasData"
+#define BOOKMARK_KEY @"bookmark"
 #define RELATIVEPATH_KEY @"relativePath"
 
 static CFURLRef BDSKCreateURLFromFSRef(const FSRef *inRef);
@@ -71,12 +72,17 @@
 // Private concrete subclasses
 
 @interface BDSKLinkedAliasFile : BDSKLinkedFile {
-    AliasHandle alias;
+    union _BDSKLocator {
+        AliasHandle handle;
+        NSData *bookmark;
+    } alias;
     const FSRef *fileRef;
     NSString *relativePath;
     NSURL *fileURL;
+    BOOL isBookmark;
     BOOL isInitial;
-    char hasSkimNotes;
+    BOOL hasSkimNotes;
+    BOOL hasSkimNotesNeedsUpdate;
     id delegate;
 }
 
@@ -268,34 +274,74 @@
 
 @implementation BDSKLinkedAliasFile
 
-// takes possession of anAlias, even if it fails
-- (id)initWithAlias:(AliasHandle)anAlias relativePath:(NSString *)relPath 
delegate:(id<BDSKLinkedFileDelegate>)aDelegate;
+- (id)initWithURL:(NSURL *)aURL delegate:(id<BDSKLinkedFileDelegate>)aDelegate;
 {
-    BDSKASSERT(nil != anAlias || nil != relPath);
+    BDSKASSERT([aURL isFileURL]);
+    
+    NSString *aPath = [aURL path];
+    
+    BDSKASSERT(nil != aPath);
     BDSKASSERT(nil == aDelegate || [aDelegate 
respondsToSelector:@selector(basePathForLinkedFile:)]);
     
-    self = [super init];
-    if (anAlias == nil && relPath == nil) {
+    NSString *basePath = [aDelegate basePathForLinkedFile:self];
+    NSString *relPath = basePath ? [aPath relativePathFromPath:basePath] : nil;
+    AliasHandle anAlias = BDSKPathToAliasHandle((CFStringRef)aPath, 
(CFStringRef)basePath);
+    
+    if (anAlias == NULL) {
         [self release];
         self = nil;
-    } else if (self == nil) {
-        BDSKDisposeAliasHandle(anAlias);
     } else {
-        fileRef = NULL; // this is updated lazily, as we don't know the base 
path at this point
-        alias = anAlias;
-        relativePath = [relPath copy];
-        delegate = aDelegate;
-        fileURL = nil;
-        isInitial = YES;
-        hasSkimNotes = -1;
+        self = [super init];
+        if (self) {
+            fileRef = NULL; // this is updated below if we know the base pat
+            alias.handle = anAlias;
+            isBookmark = NO;
+            relativePath = [relPath copy];
+            delegate = aDelegate;
+            fileURL = nil;
+            isInitial = YES;
+            hasSkimNotes = NO;
+            hasSkimNotesNeedsUpdate = YES;
+            if (basePath)
+                // this initalizes the FSRef and update the alias
+                [self updateFileRef];
+        }
     }
-    return self;    
+    return self;
 }
 
-- (id)initWithAliasData:(NSData *)data relativePath:(NSString *)relPath 
delegate:(id<BDSKLinkedFileDelegate>)aDelegate;
+- (id)initWithData:(NSData *)data isBookmark:(BOOL)isBookmarkData 
relativePath:(NSString *)relPath delegate:(id<BDSKLinkedFileDelegate>)aDelegate;
 {
-    AliasHandle anAlias = BDSKDataToAliasHandle((CFDataRef)data);
-    return [self initWithAlias:anAlias relativePath:relPath 
delegate:aDelegate];
+    BDSKASSERT(nil != data || nil != relPath);
+    BDSKASSERT(nil == aDelegate || [aDelegate 
respondsToSelector:@selector(basePathForLinkedFile:)]);
+    
+    AliasHandle anAlias = NULL;
+    if (isBookmarkData == NO) {
+        anAlias = BDSKDataToAliasHandle((CFDataRef)data);
+        if (anAlias == NULL) data = nil;
+    }
+    
+    if (data == nil && relPath == nil) {
+        [self release];
+        self = nil;
+    } else {
+        self = [super init];
+        if (self) {
+            fileRef = NULL; // this is updated lazily, as we don't know the 
base path at this point
+            if (isBookmarkData)
+                alias.bookmark = [data copy];
+            else
+                alias.handle = anAlias;
+            isBookmark = isBookmarkData;
+            relativePath = [relPath copy];
+            delegate = aDelegate;
+            fileURL = nil;
+            isInitial = YES;
+            hasSkimNotes = NO;
+            hasSkimNotesNeedsUpdate = YES;
+        }
+    }
+    return self;
 }
 
 - (id)initWithBase64String:(NSString *)base64String 
delegate:(id<BDSKLinkedFileDelegate>)aDelegate;
@@ -315,7 +361,8 @@
     }
     
     NSString *relPath = nil;
-    NSData *aliasData = nil;
+    NSData *fileData = nil;
+    BOOL isBookmarkData = NO;
     
     if ([base64String hasPrefix:ENCODED_PLIST_PREFIX]) {
         if (([base64String length] % 4) != 0) {
@@ -342,7 +389,11 @@
                 dictionary = BDSKDictionaryFromArchivedData(data) ?: 
BDSKDictionaryFromPlistData(data);
             else
                 dictionary = BDSKDictionaryFromPlistData(data) ?: 
BDSKDictionaryFromArchivedData(data);
-            aliasData = [dictionary objectForKey:ALIASDATA_KEY];
+            fileData = [dictionary objectForKey:ALIASDATA_KEY];
+            if (fileData == nil) {
+                fileData = [dictionary objectForKey:BOOKMARK_KEY];
+                isBookmarkData = (fileData != nil);
+            }
             relPath = [dictionary objectForKey:RELATIVEPATH_KEY];
             [data release];
         }
@@ -350,37 +401,9 @@
         relPath = base64String;
     }
     
-    return [self initWithAliasData:aliasData relativePath:relPath 
delegate:aDelegate];
+    return [self initWithData:fileData isBookmark:isBookmarkData 
relativePath:relPath delegate:aDelegate];
 }
 
-
-- (id)initWithURL:(NSURL *)aURL delegate:(id<BDSKLinkedFileDelegate>)aDelegate;
-{
-    BDSKASSERT([aURL isFileURL]);
-    
-    NSString *aPath = [aURL path];
-    
-    BDSKASSERT(nil != aPath);
-    BDSKASSERT(nil == aDelegate || [aDelegate 
respondsToSelector:@selector(basePathForLinkedFile:)]);
-    
-    NSString *basePath = [aDelegate basePathForLinkedFile:self];
-    NSString *relPath = basePath ? [aPath relativePathFromPath:basePath] : nil;
-    AliasHandle anAlias = BDSKPathToAliasHandle((CFStringRef)aPath, 
(CFStringRef)basePath);
-    
-    if (anAlias == NULL) {
-        [self release];
-        self = nil;
-    } else {
-        self = [self initWithAlias:anAlias relativePath:relPath 
delegate:aDelegate];
-        if (self) {
-            if (basePath)
-                // this initalizes the FSRef and update the alias
-                [self updateFileRef];
-        }
-    }
-    return self;
-}
-
 - (id)initWithURLString:(NSString *)aString;
 {
     BDSKASSERT_NOT_REACHED("Attempt to initialize BDSKLinkedAliasFile with a 
URL string");
@@ -390,24 +413,32 @@
 - (id)initWithCoder:(NSCoder *)coder
 {
     NSData *data = nil;
+    BOOL isBookmarkData = NO;
     NSString *relPath = nil;
     if ([coder allowsKeyedCoding]) {
         data = [coder decodeObjectForKey:ALIASDATA_KEY];
+        if (data == nil) {
+            data = [coder decodeObjectForKey:BOOKMARK_KEY];
+            isBookmarkData = (data != nil);
+        }
         relPath = [coder decodeObjectForKey:RELATIVEPATH_KEY];
     } else {
         data = [coder decodeObject];
         relPath = [coder decodeObject];
     }
-    return [self initWithAliasData:data relativePath:relPath delegate:nil];
+    return [self initWithData:data isBookmark:isBookmarkData 
relativePath:relPath delegate:nil];
 }
 
 - (void)encodeWithCoder:(NSCoder *)coder
 {
+    NSData *data = [self aliasDataRelativeToPath:[delegate 
basePathForLinkedFile:self]];
     if ([coder allowsKeyedCoding]) {
-        [coder encodeObject:[self aliasDataRelativeToPath:[delegate 
basePathForLinkedFile:self]] forKey:ALIASDATA_KEY];
+        [coder encodeObject:data forKey:ALIASDATA_KEY];
+        if (data == nil && isBookmark && alias.bookmark)
+            [coder encodeObject:alias.bookmark forKey:BOOKMARK_KEY];
         [coder encodeObject:relativePath forKey:RELATIVEPATH_KEY];
     } else {
-        [coder encodeObject:[self aliasDataRelativeToPath:[delegate 
basePathForLinkedFile:self]]];
+        [coder encodeObject:data];
         [coder encodeObject:relativePath];
     }
 }
@@ -415,7 +446,11 @@
 - (void)dealloc
 {
     BDSKZONEDESTROY(fileRef);
-    BDSKDisposeAliasHandle(alias); alias = NULL;
+    if (isBookmark) {
+        BDSKDESTROY(alias.bookmark);
+    } else {
+        BDSKDisposeAliasHandle(alias.handle); alias.handle = NULL;
+    }
     BDSKDESTROY(relativePath);
     BDSKDESTROY(fileURL);
     [super dealloc];
@@ -423,7 +458,13 @@
 
 - (id)copyWithZone:(NSZone *)aZone
 {
-    return [[[self class] allocWithZone:aZone] initWithAliasData:[self 
aliasDataRelativeToPath:[delegate basePathForLinkedFile:self]] 
relativePath:relativePath delegate:delegate];
+    NSData *data = [self aliasDataRelativeToPath:[delegate 
basePathForLinkedFile:self]];
+    BOOL isBookmarkData = NO;
+    if (data == nil && isBookmark && alias.bookmark){
+        data = alias.bookmark;
+        isBookmarkData = YES;
+    }
+    return [[[self class] allocWithZone:aZone] initWithData:data 
isBookmark:isBookmarkData relativePath:relativePath delegate:delegate];
 }
 
 // Should we implement -isEqual: and -hash?
@@ -466,7 +507,7 @@
     if (aURL != fileURL) {
         [fileURL release];
         fileURL = [aURL retain];
-        hasSkimNotes = -1;
+        hasSkimNotesNeedsUpdate = YES;
         if (isInitial == NO)
             [delegate performSelector:@selector(linkedFileURLChanged:) 
withObject:self afterDelay:0.0];
     }
@@ -493,10 +534,15 @@
             shouldUpdate = hasRef = BDSKPathToFSRef((CFStringRef)path, &aRef);
         }
         
-        if (hasRef == false && alias != NULL) {
-            hasRef = BDSKAliasHandleToFSRef(alias, hasBaseRef ? &baseRef : 
NULL, &aRef, &shouldUpdate);
+        if (hasRef == false && isBookmark == NO && alias.handle != NULL) {
+            hasRef = BDSKAliasHandleToFSRef(alias.handle, hasBaseRef ? 
&baseRef : NULL, &aRef, &shouldUpdate);
             shouldUpdate = (shouldUpdate || relativePath == nil) && hasBaseRef 
&& hasRef;
         }
+        if (hasRef == false && isBookmark && alias.bookmark != nil) {
+            NSURL *aURL = [NSURL URLByResolvingBookmarkData:alias.bookmark 
options:NSURLBookmarkResolutionWithoutUI | 
NSURLBookmarkResolutionWithoutMounting relativeToURL:(basePath ? [NSURL 
fileURLWithPath:basePath] : nil) bookmarkDataIsStale:NULL error:NULL];
+            hasRef = BDSKPathToFSRef((CFStringRef)[aURL path], &aRef);
+            shouldUpdate = hasBaseRef && hasRef;
+        }
         
         if (hasRef)
             [self setFileRef:&aRef];
@@ -564,9 +610,11 @@
 }
 
 - (BOOL)hasSkimNotes {
-    if (hasSkimNotes == -1)
+    if (hasSkimNotesNeedsUpdate) {
         hasSkimNotes = [[fileURL SkimNotes] count] > 0;
-    return hasSkimNotes == 1;
+        hasSkimNotesNeedsUpdate = NO;
+    }
+    return hasSkimNotes;
 }
 
 - (NSData *)aliasDataRelativeToPath:(NSString *)basePath;
@@ -589,8 +637,8 @@
     if (anAlias != NULL) {
         data = BDSKCopyAliasHandleToData(anAlias);
         BDSKDisposeAliasHandle(anAlias);
-    } else if (alias != NULL) {
-        data = BDSKCopyAliasHandleToData(alias);
+    } else if (isBookmark == NO && alias.handle != NULL) {
+        data = BDSKCopyAliasHandleToData(alias.handle);
     }
     
     return [(NSData *)data autorelease];
@@ -603,10 +651,15 @@
         newBasePath = [delegate basePathForLinkedFile:self];
     NSData *data = noAlias ? nil : [self aliasDataRelativeToPath:newBasePath];
     NSString *path = [self path];
+    NSString *dataKey = ALIASDATA_KEY;
     path = path && newBasePath ? [path relativePathFromPath:newBasePath] : 
relativePath;
     if (path == nil && noAlias)
         data = [self aliasDataRelativeToPath:newBasePath];
-    NSDictionary *dictionary = data ? [NSDictionary 
dictionaryWithObjectsAndKeys:data, ALIASDATA_KEY, path, RELATIVEPATH_KEY, nil] 
: [NSDictionary dictionaryWithObjectsAndKeys:path, RELATIVEPATH_KEY, nil];
+    if (data == nil && (noAlias == NO || path == nil) && isBookmark) {
+        data = alias.bookmark;
+        dataKey = BOOKMARK_KEY;
+    }
+    NSDictionary *dictionary = data ? [NSDictionary 
dictionaryWithObjectsAndKeys:data, dataKey, path, RELATIVEPATH_KEY, nil] : 
[NSDictionary dictionaryWithObjectsAndKeys:path, RELATIVEPATH_KEY, nil];
     if (saveArchivedData)
         return [[NSKeyedArchiver archivedDataWithRootObject:dictionary] 
base64String];
     else
@@ -616,15 +669,20 @@
 - (void)updateAliasWithPath:(NSString *)aPath basePath:(NSString *)basePath {
     AliasHandle anAlias = BDSKPathToAliasHandle((CFStringRef)aPath, 
(CFStringRef)basePath);
     if (anAlias != NULL) {
-        AliasHandle saveAlias = alias;
-        alias = anAlias;
+        BOOL saveIsBookmark = isBookmark;
+        union _BDSKLocator saveAlias = alias;
+        alias.handle = anAlias;
+        isBookmark = NO;
         [self updateFileRef];
         if (fileRef == NULL) {
             BDSKDisposeAliasHandle(anAlias);
             alias = saveAlias;
+            isBookmark = saveIsBookmark;
             [self updateFileRef];
+        } else if (saveIsBookmark) {
+            [saveAlias.bookmark release];
         } else {
-            BDSKDisposeAliasHandle(saveAlias);
+            BDSKDisposeAliasHandle(saveAlias.handle);
         }
     }
 }
@@ -686,13 +744,21 @@
     Boolean didUpdate;
     
     // update the alias
-    if (alias != NULL)
+    if (isBookmark == NO && alias.handle != NULL) {
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
-        FSUpdateAlias(BDSKBaseRefIfOnSameVolume(baseRef, fileRef), fileRef, 
alias, &didUpdate);
+        FSUpdateAlias(BDSKBaseRefIfOnSameVolume(baseRef, fileRef), fileRef, 
alias.handle, &didUpdate);
 #pragma clang diagnostic pop
-    else
-        alias = BDSKFSRefToAliasHandle(fileRef, baseRef);
+    } else {
+        AliasHandle anAlias = BDSKFSRefToAliasHandle(fileRef, baseRef);
+        if (anAlias) {
+            if (isBookmark) {
+                BDSKDESTROY(alias.bookmark);
+                isBookmark = NO;
+            }
+            alias.handle = anAlias;
+        }
+    }
     
     // update the relative path
     [relativePath autorelease];
@@ -700,7 +766,7 @@
 }
 
 - (void)updateHasSkimNotes {
-    hasSkimNotes = -1;
+    hasSkimNotesNeedsUpdate = YES;
     if (isInitial == NO)
         [delegate performSelector:@selector(linkedFileURLChanged:) 
withObject:self afterDelay:0.0];
 }

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



_______________________________________________
Bibdesk-commit mailing list
Bibdesk-commit@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bibdesk-commit

Reply via email to