Revision: 26844
          http://sourceforge.net/p/bibdesk/svn/26844
Author:   hofman
Date:     2021-09-11 09:40:06 +0000 (Sat, 11 Sep 2021)
Log Message:
-----------
Revert part of r26842 which hiked along

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

Modified: trunk/bibdesk/BDSKLinkedFile.m
===================================================================
--- trunk/bibdesk/BDSKLinkedFile.m      2021-09-11 09:13:44 UTC (rev 26843)
+++ trunk/bibdesk/BDSKLinkedFile.m      2021-09-11 09:40:06 UTC (rev 26844)
@@ -94,6 +94,7 @@
 
 @interface BDSKLinkedAliasFile : BDSKLinkedFile {
     id alias; // can be a BDSKAlias or bookmark NSData
+    id fileRef; // can be a BDSKFileRef or a file reference NSURL
     NSString *relativePath;
     NSURL *fileURL;
     BOOL isInitial;
@@ -101,25 +102,13 @@
     BOOL hasSkimNotesNeedsUpdate;
     id delegate;
 }
-- (void)updateFileURL;
-- (NSData *)copyAliasDataRelativeToPath:(NSString *)newBasePath;
-@end
 
-#pragma mark -
-
-@interface BDSKAliasLinkedFile : BDSKLinkedAliasFile {
-    const FSRef *fileRef;
-}
 - (void)updateFileRef;
-@end
+- (void)updateFileURL;
 
-#pragma mark -
+- (NSData *)copyAliasDataRelativeToPath:(NSString *)newBasePath;
+- (NSData *)copyBookmarkDataRelativeToPath:(NSString *)newBasePath;
 
-@interface BDSKBookmarkLinkedFile : BDSKLinkedAliasFile {
-    NSURL *fileRefURL;
-}
-- (void)updateFileRefURL;
-- (NSData *)copyBookmarkDataRelativeToPath:(NSString *)newBasePath;
 @end
 
 #pragma mark -
@@ -150,10 +139,6 @@
     saveRelativePathOnly = [[NSUserDefaults standardUserDefaults] 
boolForKey:BDSKSaveLinkedFilesAsRelativePathOnlyKey];
     saveArchivedData = [[NSUserDefaults standardUserDefaults] 
boolForKey:BDSKSaveLinkedFilesAsArchivedDataKey];
     wantsBookmark = saveArchivedData == NO && [[NSUserDefaults 
standardUserDefaults] boolForKey:BDSKSaveLinkedFilesAsBookmarkDataKey];
-    
-    NSString *fileClassName = wantsBookmark ? @"BDSKBookmarkLinkedFile" : 
@"BDSKAliasLinkedFile";
-    [NSKeyedUnarchiver setClass:NSClassFromString(fileClassName) 
forClassName:@"BDSKLinkedAliasFile"];
-    [NSUnarchiver decodeClassName:@"BDSKLinkedAliasFile" 
asClassName:fileClassName];
 }
 
 + (id)allocWithZone:(NSZone *)aZone {
@@ -261,7 +246,7 @@
 
 - (id)initWithURL:(NSURL *)aURL delegate:(id<BDSKLinkedFileDelegate>)aDelegate 
{
     if([aURL isFileURL])
-        return (id)[(wantsBookmark ? [BDSKBookmarkLinkedFile alloc] : 
[BDSKAliasLinkedFile alloc]) initWithURL:aURL delegate:aDelegate];
+        return (id)[[BDSKLinkedAliasFile alloc] initWithURL:aURL 
delegate:aDelegate];
     else if (aURL)
         return (id)[[BDSKLinkedURL alloc] initWithURL:aURL delegate:aDelegate];
     else
@@ -269,7 +254,7 @@
 }
 
 - (id)initWithBase64String:(NSString *)base64String 
delegate:(id<BDSKLinkedFileDelegate>)aDelegate {
-    return (id)[(wantsBookmark ? [BDSKBookmarkLinkedFile alloc] : 
[BDSKAliasLinkedFile alloc]) initWithBase64String:base64String 
delegate:aDelegate];
+    return (id)[[BDSKLinkedAliasFile alloc] initWithBase64String:base64String 
delegate:aDelegate];
 }
 
 - (id)initWithURLString:(NSString *)aString {
@@ -302,6 +287,7 @@
     } else {
         self = [super init];
         if (self) {
+            fileRef = nil; // this is updated lazily, as we don't know the 
base path at this point
             alias = [anAlias retain];
             relativePath = [relPath copy];
             delegate = aDelegate;
@@ -315,8 +301,24 @@
 }
 
 - (id)initWithURL:(NSURL *)aURL delegate:(id<BDSKLinkedFileDelegate>)aDelegate 
{
-    BDSKASSERT_NOT_REACHED("Attempt to initialize BDSKLinkedAliasFile directly 
with a URL");
-    return nil;
+    BDSKASSERT([aURL isFileURL]);
+    
+    NSString *aPath = [aURL path];
+    
+    BDSKASSERT(nil != aPath);
+    
+    NSString *basePath = [aDelegate basePathForLinkedFile:self];
+    NSString *relPath = basePath ? [aPath relativePathFromPath:basePath] : nil;
+    id anAlias;
+    if (wantsBookmark)
+        anAlias = BDSKCreateBookmarkDataFromURL(aURL);
+    else
+        anAlias = [BDSKAlias newWithPath:aPath basePath:basePath];
+    self = [self initWithAlias:anAlias relativePath:relPath 
delegate:aDelegate];
+    [anAlias release];
+    if (self && basePath)
+        [self updateFileRef];
+    return self;
 }
 
 - (id)initWithBase64String:(NSString *)base64String 
delegate:(id<BDSKLinkedFileDelegate>)aDelegate {
@@ -383,11 +385,6 @@
 }
 
 - (id)initWithCoder:(NSCoder *)coder {
-    if ([self isMemberOfClass:[BDSKLinkedAliasFile class]]) {
-        BDSKASSERT_NOT_REACHED("Attempt to decode a BDSKLinkedAliasFile 
instance");
-        [self release];
-        self = wantsBookmark ? [BDSKBookmarkLinkedFile alloc] : 
[BDSKAliasLinkedFile alloc];
-    }
     id anAlias = nil;
     NSString *relPath = nil;
     if ([coder allowsKeyedCoding]) {
@@ -407,23 +404,33 @@
 - (void)encodeWithCoder:(NSCoder *)coder {
     // make sure the fileRef is valid
     [self updateFileURL];
+    NSData *data = nil;
+    NSString *basePath = [delegate basePathForLinkedFile:self];
     if ([coder allowsKeyedCoding]) {
-        // the alias or bookmark data is set by the subclasses
+        if (wantsBookmark) {
+            data = [self copyBookmarkDataRelativeToPath:basePath];
+            if (data)
+                [coder encodeObject:alias forKey:BOOKMARK_KEY];
+            else if ([alias isKindOfClass:[BDSKAlias class]] && (data = [alias 
copyData]))
+                [coder encodeObject:data forKey:ALIASDATA_KEY];
+        } else {
+            data = [self copyAliasDataRelativeToPath:basePath];
+            if (data)
+                [coder encodeObject:data forKey:ALIASDATA_KEY];
+            else if ([alias isKindOfClass:[NSData class]])
+                [coder encodeObject:alias forKey:BOOKMARK_KEY];
+        }
         [coder encodeObject:relativePath forKey:RELATIVEPATH_KEY];
     } else {
-        NSData *data = [self copyAliasDataRelativeToPath:[delegate 
basePathForLinkedFile:self]];
+        data = [self copyAliasDataRelativeToPath:basePath];
         [coder encodeObject:data];
         [coder encodeObject:relativePath];
-        [data release];
     }
+    [data release];
 }
 
-// always encode subclasses as BDSKLinkedAliasFile
-- (Class)classForKeyedArchiver { return [BDSKLinkedAliasFile class]; }
-- (Class)classForArchiver { return [BDSKLinkedAliasFile class]; }
-- (Class)classForPortCoder { return [BDSKLinkedAliasFile class]; }
-
 - (void)dealloc {
+    BDSKDESTROY(fileRef);
     BDSKDESTROY(alias);
     BDSKDESTROY(relativePath);
     BDSKDESTROY(fileURL);
@@ -433,11 +440,21 @@
 - (id)copyWithZone:(NSZone *)aZone {
     // make sure the fileRef is valid
     [self updateFileURL];
-    NSData *data = [self copyAliasDataRelativeToPath:[delegate 
basePathForLinkedFile:self]];
-    id anAlias = [BDSKAlias newWithData:data];
-    [data release];
-    if (anAlias == nil && [alias isKindOfClass:[NSData class]])
-        anAlias = [alias copy];
+    id anAlias = nil;
+    if (wantsBookmark) {
+        anAlias = [self copyBookmarkDataRelativeToPath:[delegate 
basePathForLinkedFile:self]];
+        if (anAlias == nil && [alias isKindOfClass:[BDSKAlias class]]) {
+            NSData *data = [alias copyData];
+            anAlias = [BDSKAlias newWithData:data];
+            [data release];
+        }
+    } else {
+        NSData *data = [self copyAliasDataRelativeToPath:[delegate 
basePathForLinkedFile:self]];
+        anAlias = [BDSKAlias newWithData:data];
+        [data release];
+        if (anAlias == nil && [alias isKindOfClass:[NSData class]])
+            anAlias = [alias copy];
+    }
     self = [[[self class] allocWithZone:aZone] initWithAlias:anAlias 
relativePath:relativePath delegate:delegate];
     [anAlias release];
     return self;
@@ -482,179 +499,25 @@
     }
 }
 
-// this is really implemented by the subclasses
-- (void)updateFileURL {
-    if (fileURL == nil && relativePath) {
-        NSString *basePath = [delegate basePathForLinkedFile:self];
-        if (basePath)
-            fileURL = [[NSURL alloc] initFileURLWithPath:[relativePath 
isAbsolutePath] ? relativePath : [[basePath 
stringByAppendingPathComponent:relativePath] stringByStandardizingPath]];
-    }
-}
-
-- (NSURL *)URL {
-    [self updateFileURL];
-    return fileURL;
-}
-
-- (NSURL *)displayURL {
-    NSURL *displayURL = [self URL];
-    if (displayURL == nil && relativePath) {
-        NSString *basePath = [delegate basePathForLinkedFile:self];
-        displayURL = basePath ? [NSURL URLWithString:[relativePath 
stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet 
URLPathAllowedCharacterSet]] relativeToURL:[NSURL fileURLWithPath:basePath 
isDirectory:YES]] : [NSURL fileURLWithPath:relativePath isDirectory:NO];
-    }
-    return displayURL;
-}
-
-- (BOOL)hasSkimNotes {
-    if (hasSkimNotesNeedsUpdate) {
-        hasSkimNotes = [[fileURL SkimNotes] count] > 0;
-        hasSkimNotesNeedsUpdate = NO;
-    }
-    return hasSkimNotes;
-}
-
-- (NSData *)copyAliasDataRelativeToPath:(NSString *)basePath {
-    BDSKAlias *anAlias = NULL;
-    NSData *data = nil;
-    
-    if (fileURL) {
-        anAlias = [BDSKAlias newWithPath:[fileURL path] basePath:basePath];
-    } else if (relativePath && basePath) {
-        NSString *path = [relativePath isAbsolutePath] ? relativePath : 
[[basePath stringByAppendingPathComponent:relativePath] 
stringByStandardizingPath];
-        anAlias = [BDSKAlias newWithPath:path basePath:basePath];
-    }
-    if (anAlias != NULL) {
-        data = [anAlias copyData];
-        [anAlias release];
-    } else if ([alias isKindOfClass:[BDSKAlias class]]) {
-        data = [alias copyData];
-    }
-    
-    return data;
-}
-
-- (NSData *)copyDataRelativeToPath:(NSString *)newBasePath isBookmark:(BOOL 
*)isBookmark {
-    NSData *data = [self copyAliasDataRelativeToPath:newBasePath];
-    if (data) {
-        *isBookmark = NO;
-    } else if ([alias isKindOfClass:[NSData class]]) {
-        data = [alias retain];
-        *isBookmark = YES;
-    }
-    return data;
-}
-
-- (NSString *)stringRelativeToPath:(NSString *)newBasePath {
-    BOOL noAlias = saveRelativePathOnly && newBasePath != nil;
-    if (newBasePath == nil)
-        newBasePath = [delegate basePathForLinkedFile:self];
-    NSDictionary *dictionary  = nil;
-    // this will make sure the fileURL is valid
-    NSString *path = [self path];
-    path = path && newBasePath ? [path relativePathFromPath:newBasePath] : 
relativePath;
-    if (noAlias == NO || path == nil) {
-        BOOL isBookmark = NO;
-        NSData *data = [self copyDataRelativeToPath:newBasePath 
isBookmark:&isBookmark];
-        if (data) {
-            dictionary = [NSDictionary dictionaryWithObjectsAndKeys:data, 
(isBookmark ? BOOKMARK_KEY : ALIASDATA_KEY), path, RELATIVEPATH_KEY, nil];
-            [data release];
-        }
-    }
-    if (dictionary == nil)
-        dictionary = [NSDictionary dictionaryWithObjectsAndKeys:path, 
RELATIVEPATH_KEY, nil];
-    if (saveArchivedData)
-        return [[NSKeyedArchiver archivedDataWithRootObject:dictionary] 
base64String];
+- (NSURL *)newPathURL {
+    if (fileRef == nil)
+        return nil;
+    else if (wantsBookmark)
+        return (NSURL *)CFURLCreateFilePathURL(kCFAllocatorDefault, 
(CFURLRef)fileRef, NULL);
     else
-        return [[NSPropertyListSerialization dataWithPropertyList:dictionary 
format:NSPropertyListBinaryFormat_v1_0 options:0 error:NULL] base64String];
+        return BDSKCreateURLFromFSRef([fileRef fsRef]);
 }
 
-// This is called when the file is added (new or initially),
-// the document URL changes, or with aPath != nil after an autofile
-// implemented by the subclasses
-- (void)updateWithPath:(NSString *)aPath {}
-
-- (void)updateHasSkimNotes {
-    hasSkimNotesNeedsUpdate = YES;
-    if (isInitial == NO)
-        [delegate performSelector:@selector(linkedFileURLChanged:) 
withObject:self afterDelay:0.0];
-}
-
-@end
-
-#pragma mark -
-
-@implementation BDSKAliasLinkedFile
-
-- (id)initWithURL:(NSURL *)aURL delegate:(id<BDSKLinkedFileDelegate>)aDelegate 
{
-    BDSKASSERT([aURL isFileURL]);
-    
-    NSString *aPath = [aURL path];
-    
-    BDSKASSERT(nil != aPath);
-    
-    NSString *basePath = [aDelegate basePathForLinkedFile:self];
-    NSString *relPath = basePath ? [aPath relativePathFromPath:basePath] : nil;
-    id anAlias = [BDSKAlias newWithPath:aPath basePath:basePath];
-    self = [self initWithAlias:anAlias relativePath:relPath 
delegate:aDelegate];
-    [anAlias release];
-    if (self && basePath)
-        [self updateFileRef];
-    return self;
-}
-
-- (void)encodeWithCoder:(NSCoder *)coder {
-    [super encodeWithCoder:coder];
-    if ([coder allowsKeyedCoding]) {
-        NSData *data = [self copyAliasDataRelativeToPath:[delegate 
basePathForLinkedFile:self]];
-        if (data)
-            [coder encodeObject:data forKey:ALIASDATA_KEY];
-        else if ([alias isKindOfClass:[NSData class]])
-            [coder encodeObject:alias forKey:BOOKMARK_KEY];
-        [data release];
-    }
-}
-
-- (void)dealloc {
-    BDSKZONEDESTROY(fileRef);
-    [super dealloc];
-}
-
-- (id)copyWithZone:(NSZone *)aZone {
-    // make sure the fileRef is valid
-    [self updateFileURL];
-    NSData *data = [self copyAliasDataRelativeToPath:[delegate 
basePathForLinkedFile:self]];
-    id anAlias = [BDSKAlias newWithData:data];
-    [data release];
-    if (anAlias == nil && [alias isKindOfClass:[NSData class]])
-        anAlias = [alias copy];
-    self = [[[self class] allocWithZone:aZone] initWithAlias:anAlias 
relativePath:relativePath delegate:delegate];
-    [anAlias release];
-    return self;
-}
-
-- (void)setFileRef:(FSRef *)aRef {
-    BDSKZONEDESTROY(fileRef);
-    if (aRef != NULL) {
-        FSRef *newRef = (FSRef *)NSZoneMalloc([self zone], sizeof(FSRef));
-        if (newRef) {
-            bcopy(aRef, newRef, sizeof(FSRef));
-            fileRef = newRef;
-        } else {
-            [self release];
-            self = nil;
-        }
-    }
-}
-
 - (void)updateAliasWithBaseRef:(FSRef *)baseRef {
     BDSKASSERT(fileRef != nil);
     BDSKASSERT(baseRef != NULL);
+    BDSKASSERT(wantsBookmark == NO);
     
     // update the alias
     if ([alias isKindOfClass:[BDSKAlias class]]) {
-        [alias updateWithFSRef:fileRef baseRef:baseRef];
+        [alias updateWithFSRef:[fileRef fsRef] baseRef:baseRef];
     } else {
-        BDSKAlias *anAlias = [BDSKAlias newWithFSRef:fileRef baseRef:baseRef];
+        BDSKAlias *anAlias = [BDSKAlias newWithFSRef:[fileRef fsRef] 
baseRef:baseRef];
         if (anAlias) {
             BDSKDESTROY(alias);
             alias = anAlias;
@@ -662,55 +525,130 @@
     }
 }
 
+- (void)updateBookmark {
+    BDSKASSERT(fileURL != nil);
+    BDSKASSERT(wantsBookmark);
+    
+    // update the bookmark
+    NSData *data = BDSKCreateBookmarkDataFromURL(fileURL ?: [fileRef 
filePathURL]);
+    if (data) {
+        [alias release];
+        alias = data;
+    }
+}
+
 - (void)updateFileRef {
     NSString *basePath = [delegate basePathForLinkedFile:self];
     BOOL shouldUpdate = NO;
     
-    FSRef baseRef;
-    BOOL hasBaseRef = BDSKPathToFSRef(basePath, &baseRef);
-    
-    if (fileRef == nil) {
-        FSRef aRef;
-        BOOL hasRef = NO;
-        
-        if (fileURL) {
-            hasRef = BDSKPathToFSRef([fileURL path], &aRef);
-            shouldUpdate = hasBaseRef && hasRef;
+    if (wantsBookmark) {
+        // using bookmark and NSURL
+        if (fileRef == nil) {
+            NSURL *refURL = nil;
+
+            if (fileURL) {
+                refURL = (NSURL 
*)CFURLCreateFileReferenceURL(kCFAllocatorDefault, (CFURLRef)fileURL, NULL);
+                shouldUpdate = basePath != nil && refURL != nil;
+            }
+            
+            if (refURL == nil && basePath && relativePath) {
+                NSURL *aURL = [NSURL fileURLWithPath:[relativePath 
isAbsolutePath] ? relativePath : [basePath 
stringByAppendingPathComponent:relativePath] isDirectory:NO];
+                refURL = (NSURL 
*)CFURLCreateFileReferenceURL(kCFAllocatorDefault, (CFURLRef)aURL, NULL);
+                shouldUpdate = refURL != nil;
+            }
+            
+            if (refURL == nil) {
+                if ([alias isKindOfClass:[NSData class]]) {
+                    NSURL *aURL = (NSURL 
*)CFURLCreateByResolvingBookmarkData(kCFAllocatorDefault, (CFDataRef)alias, 
kCFURLBookmarkResolutionWithoutUIMask | 
kCFURLBookmarkResolutionWithoutMountingMask, NULL, NULL, (Boolean 
*)&shouldUpdate, NULL);
+                    if (aURL) {
+                        refURL = (NSURL 
*)CFURLCreateFileReferenceURL(kCFAllocatorDefault, (CFURLRef)aURL, NULL);
+                        [aURL release];
+                    }
+                    shouldUpdate = shouldUpdate && basePath != nil && refURL 
!= nil;
+                } else if ([alias isKindOfClass:[BDSKAlias class]]) {
+                    FSRef aRef, baseRef;
+                    BOOL ignored, hasBaseRef = BDSKPathToFSRef(basePath, 
&baseRef);
+                    if ([alias getFSRef:&aRef baseRef:hasBaseRef ? &baseRef : 
NULL shouldUpdate:&ignored]){
+                        NSURL *aURL = BDSKCreateURLFromFSRef(&aRef);
+                        if (aURL) {
+                            refURL = (NSURL 
*)CFURLCreateFileReferenceURL(kCFAllocatorDefault, (CFURLRef)aURL, NULL);
+                            [aURL release];
+                        }
+                    }
+                    shouldUpdate = hasBaseRef && refURL != nil;
+                }
+            }
+            
+            if (refURL != nil) {
+                [fileRef release];
+                fileRef = refURL;
+            }
+        } else if (relativePath == nil) {
+            shouldUpdate = basePath != nil;
         }
         
-        if (hasRef == NO && hasBaseRef && relativePath) {
-            NSString *path = [relativePath isAbsolutePath] ? relativePath : 
[basePath stringByAppendingPathComponent:relativePath];
-            shouldUpdate = hasRef = BDSKPathToFSRef(path, &aRef);
+        if ((shouldUpdate || fileURL == nil) && fileRef != nil) {
+            NSURL *aURL = [self newPathURL];
+            if (aURL != nil) {
+                if (fileURL == nil)
+                    fileURL = [aURL retain];
+                if (shouldUpdate) {
+                    [self updateBookmark];
+                    [self setRelativePath:[aURL path] fromPath:basePath];
+                }
+                [aURL release];
+            }
         }
         
-        if (hasRef == NO) {
-            if ([alias isKindOfClass:[BDSKAlias class]]) {
-                hasRef = [alias getFSRef:&aRef baseRef:hasBaseRef ? &baseRef : 
NULL shouldUpdate:&shouldUpdate];
-                shouldUpdate = (shouldUpdate || relativePath == nil) && 
hasBaseRef && hasRef;
-            } else if ([alias isKindOfClass:[NSData class]]) {
-                NSURL *aURL = [NSURL URLByResolvingBookmarkData:alias 
options:NSURLBookmarkResolutionWithoutUI relativeToURL:nil 
bookmarkDataIsStale:NULL error:NULL];
-                hasRef = BDSKPathToFSRef([aURL path], &aRef);
+    } else {
+        // using AliasHandle and FSRef
+        FSRef baseRef;
+        BOOL hasBaseRef = BDSKPathToFSRef(basePath, &baseRef);
+        
+        if (fileRef == nil) {
+            FSRef aRef;
+            BOOL hasRef = NO;
+            
+            if (fileURL) {
+                hasRef = BDSKPathToFSRef([fileURL path], &aRef);
                 shouldUpdate = hasBaseRef && hasRef;
             }
+            
+            if (hasRef == NO && hasBaseRef && relativePath) {
+                NSString *path = [relativePath isAbsolutePath] ? relativePath 
: [basePath stringByAppendingPathComponent:relativePath];
+                shouldUpdate = hasRef = BDSKPathToFSRef(path, &aRef);
+            }
+            
+            if (hasRef == NO) {
+                if ([alias isKindOfClass:[BDSKAlias class]]) {
+                    hasRef = [alias getFSRef:&aRef baseRef:hasBaseRef ? 
&baseRef : NULL shouldUpdate:&shouldUpdate];
+                    shouldUpdate = (shouldUpdate || relativePath == nil) && 
hasBaseRef && hasRef;
+                } else if ([alias isKindOfClass:[NSData class]]) {
+                    NSURL *aURL = [NSURL URLByResolvingBookmarkData:alias 
options:NSURLBookmarkResolutionWithoutUI relativeToURL:nil 
bookmarkDataIsStale:NULL error:NULL];
+                    hasRef = BDSKPathToFSRef([aURL path], &aRef);
+                    shouldUpdate = hasBaseRef && hasRef;
+                }
+            }
+            
+            if (hasRef) {
+                [fileRef release];
+                fileRef = [[BDSKFileRef alloc] initWithFSRef:&aRef];
+            }
+        } else if (relativePath == nil) {
+            shouldUpdate = hasBaseRef;
         }
         
-        if (hasRef) {
-            [self setFileRef:&aRef];
-        }
-    } else if (relativePath == nil) {
-        shouldUpdate = hasBaseRef;
-    }
-    
-    if ((shouldUpdate || fileURL == nil) && fileRef != nil) {
-        NSURL *aURL = BDSKCreateURLFromFSRef(fileRef);
-        if (aURL != nil) {
-            if (fileURL == nil)
-                fileURL = [aURL retain];
-            if (shouldUpdate) {
-                [self updateAliasWithBaseRef:&baseRef];
-                [self setRelativePath:[aURL path] fromPath:basePath];
+        if ((shouldUpdate || fileURL == nil) && fileRef != nil) {
+            NSURL *aURL = [self newPathURL];
+            if (aURL != nil) {
+                if (fileURL == nil)
+                    fileURL = [aURL retain];
+                if (shouldUpdate) {
+                    [self updateAliasWithBaseRef:&baseRef];
+                    [self setRelativePath:[aURL path] fromPath:basePath];
+                }
+                [aURL release];
             }
-            [aURL release];
         }
     }
 }
@@ -720,301 +658,102 @@
     NSURL *aURL = nil;
     
     if (fileRef != nil) {
-        aURL = BDSKCreateURLFromFSRef(fileRef);
+        aURL = [self newPathURL];
         if (aURL == nil)
             // fileRef was invalid, try to update it
-            BDSKZONEDESTROY(fileRef);
+            BDSKDESTROY(fileRef);
     }
     if (aURL == nil) {
         // fileRef was nil or invalid
         [self updateFileRef];
-        aURL = BDSKCreateURLFromFSRef(fileRef);
+        aURL = [self newPathURL];
     }
     
     if ([aURL isEqual:fileURL] == NO && (aURL != nil || hadFileURL)) {
-        FSRef aRef;
-        if (BDSKPathToFSRef([fileURL path], &aRef)) {
-            // the file was replaced, reference the replacement rather than 
the moved file
-            // this is what Dropbox does with file updates
-            [self setFileRef:&aRef];
-            [aURL release];
-            aURL =BDSKCreateURLFromFSRef(fileRef);
-            NSString *basePath = [delegate basePathForLinkedFile:self];
-            FSRef baseRef;
-            if (BDSKPathToFSRef(basePath, &baseRef)) {
-                [self updateAliasWithBaseRef:&baseRef];
-                [self setRelativePath:[aURL path] fromPath:basePath];
-            }
-        }
-        [self setFileURL:aURL];
-    }
-    [aURL release];
-    isInitial = NO;
-}
-
-- (NSData *)copyAliasDataRelativeToPath:(NSString *)basePath {
-    BDSKAlias *anAlias = NULL;
-    NSData *data = nil;
-    
-    if (fileRef) {
-        FSRef baseRef;
-        BOOL hasBaseRef = BDSKPathToFSRef(basePath, &baseRef);
-        anAlias = [BDSKAlias newWithFSRef:fileRef baseRef:hasBaseRef ? 
&baseRef : NULL];
-    } else if (relativePath && basePath) {
-        NSString *path = [relativePath isAbsolutePath] ? relativePath : 
[[basePath stringByAppendingPathComponent:relativePath] 
stringByStandardizingPath];
-        anAlias = [BDSKAlias newWithPath:path basePath:basePath];
-    }
-    if (anAlias != NULL) {
-        data = [anAlias copyData];
-        [anAlias release];
-    } else if ([alias isKindOfClass:[BDSKAlias class]]) {
-        data = [alias copyData];
-    }
-    
-    return data;
-}
-
-- (void)setAliasWithPath:(NSString *)aPath basePath:(NSString *)basePath {
-    id anAlias = [BDSKAlias newWithPath:aPath basePath:basePath];
-    if (anAlias != nil) {
-        id saveAlias = alias;
-        alias = anAlias;
-        [self updateFileRef];
-        if (fileRef == nil) {
-            [anAlias release];
-            alias = saveAlias;
-            [self updateFileRef];
-        } else {
-            [saveAlias release];
-        }
-    }
-}
-
-// This is called when the file is added (new or initially),
-// the document URL changes, or with aPath != nil after an autofile
-- (void)updateWithPath:(NSString *)aPath {
-    NSString *basePath = [delegate basePathForLinkedFile:self];
-    
-    if (fileRef == nil) {
-        // this does the updating if possible
-        [self updateFileRef];
-    } else {
-        NSURL *aURL = BDSKCreateURLFromFSRef(fileRef);
-        if (aURL != nil) {
-            // if the path has changed, updating will be done below
-            if (basePath && (aPath == nil || [[aURL path] 
isEqualToString:aPath])) {
-                FSRef baseRef;
-                if (BDSKPathToFSRef(basePath, &baseRef)) {
-                    [self updateAliasWithBaseRef:&baseRef];
+        if (wantsBookmark) {
+            // using bookmark and NSURL
+            NSURL *refURL = (NSURL 
*)CFURLCreateFileReferenceURL(kCFAllocatorDefault, (CFURLRef)fileURL, NULL);
+            if (refURL) {
+                // the file was replaced, reference the replacement rather 
than the moved file
+                // this is what Dropbox does with file updates
+                [fileRef release];
+                fileRef = refURL;
+                [aURL release];
+                aURL = [self newPathURL];
+                NSString *basePath = [delegate basePathForLinkedFile:self];
+                if (basePath) {
+                    [self updateBookmark];
                     [self setRelativePath:[aURL path] fromPath:basePath];
                 }
             }
-            [aURL release];
         } else {
-            // the fileRef was invalid, reset it and update
-            BDSKZONEDESTROY(fileRef);
-            [self updateFileRef];
-            if (fileRef == nil && aPath) {
-                // this can happen after an auto file to a volume, as the file 
is actually not moved but copied
-                [self setAliasWithPath:aPath basePath:basePath];
-                if (basePath)
-                    [self setRelativePath:aPath fromPath:basePath];
-            }
-        }
-    }
-    if (aPath) {
-        NSString *path = [self path];
-        if ([path isEqualToString:aPath] == NO) {
-            BOOL needsUpdate = YES;
+            // using AliasHandle and FSRef
             FSRef aRef;
-            if (BDSKPathToFSRef(aPath, &aRef)) {
-                NSURL *aURL = BDSKCreateURLFromFSRef(&aRef);
-                if ([path isEqualToString:[aURL path]]) {
-                    needsUpdate = NO;
-                } else {
-                    [self setFileRef:&aRef];
-                    [self setFileURL:aURL];
-                }
+            if (BDSKPathToFSRef([fileURL path], &aRef)) {
+                // the file was replaced, reference the replacement rather 
than the moved file
+                // this is what Dropbox does with file updates
+                [fileRef release];
+                fileRef = [[BDSKFileRef alloc] initWithFSRef:&aRef];
                 [aURL release];
-            }
-            if (needsUpdate) {
+                aURL = [self newPathURL];
+                NSString *basePath = [delegate basePathForLinkedFile:self];
                 FSRef baseRef;
                 if (BDSKPathToFSRef(basePath, &baseRef)) {
                     [self updateAliasWithBaseRef:&baseRef];
-                    [self setRelativePath:aPath fromPath:basePath];
-                } else {
-                    [self setAliasWithPath:aPath basePath:basePath];
+                    [self setRelativePath:[aURL path] fromPath:basePath];
                 }
             }
         }
+        [self setFileURL:aURL];
     }
+    [aURL release];
+    isInitial = NO;
 }
 
-@end
-
-#pragma mark -
-
-@implementation BDSKBookmarkLinkedFile
-
-- (id)initWithURL:(NSURL *)aURL delegate:(id<BDSKLinkedFileDelegate>)aDelegate 
{
-    BDSKASSERT([aURL isFileURL]);
-    
-    NSString *aPath = [aURL path];
-    
-    BDSKASSERT(nil != aPath);
-    
-    NSString *basePath = [aDelegate basePathForLinkedFile:self];
-    NSString *relPath = basePath ? [aPath relativePathFromPath:basePath] : nil;
-    id anAlias = BDSKCreateBookmarkDataFromURL(aURL);
-    self = [self initWithAlias:anAlias relativePath:relPath 
delegate:aDelegate];
-    [anAlias release];
-    if (self && basePath)
-        [self updateFileRefURL];
-    return self;
-}
-
-- (void)encodeWithCoder:(NSCoder *)coder {
-    [super encodeWithCoder:coder];
-    if ([coder allowsKeyedCoding]) {
-        NSData *data = [self copyBookmarkDataRelativeToPath:[delegate 
basePathForLinkedFile:self]];
-        if (data)
-            [coder encodeObject:alias forKey:BOOKMARK_KEY];
-        else if ([alias isKindOfClass:[BDSKAlias class]] && (data = [alias 
copyData]))
-            [coder encodeObject:data forKey:ALIASDATA_KEY];
-        [data release];
-    }
-}
-
-- (void)dealloc {
-    BDSKDESTROY(fileRefURL);
-    [super dealloc];
-}
-
-- (id)copyWithZone:(NSZone *)aZone {
-    // make sure the fileRef is valid
+- (NSURL *)URL {
     [self updateFileURL];
-    id anAlias = [self copyBookmarkDataRelativeToPath:[delegate 
basePathForLinkedFile:self]];
-    if (anAlias == nil && [alias isKindOfClass:[BDSKAlias class]]) {
-        NSData *data = [alias copyData];
-        anAlias = [BDSKAlias newWithData:data];
-        [data release];
-    }
-    self = [[[self class] allocWithZone:aZone] initWithAlias:anAlias 
relativePath:relativePath delegate:delegate];
-    [anAlias release];
-    return self;
+    return fileURL;
 }
 
-- (void)updateBookmark {
-    BDSKASSERT(fileURL != nil);
-    
-    // update the bookmark
-    NSData *data = BDSKCreateBookmarkDataFromURL(fileURL ?: [fileRefURL 
filePathURL]);
-    if (data) {
-        [alias release];
-        alias = data;
+- (NSURL *)displayURL {
+    NSURL *displayURL = [self URL];
+    if (displayURL == nil && relativePath) {
+        NSString *basePath = [delegate basePathForLinkedFile:self];
+        displayURL = basePath ? [NSURL URLWithString:[relativePath 
stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet 
URLPathAllowedCharacterSet]] relativeToURL:[NSURL fileURLWithPath:basePath 
isDirectory:YES]] : [NSURL fileURLWithPath:relativePath isDirectory:NO];
     }
+    return displayURL;
 }
 
-- (void)updateFileRefURL {
-    NSString *basePath = [delegate basePathForLinkedFile:self];
-    BOOL shouldUpdate = NO;
-    
-    // using bookmark and NSURL
-    if (fileRefURL == nil) {
-        NSURL *refURL = nil;
-
-        if (fileURL) {
-            refURL = (NSURL *)CFURLCreateFileReferenceURL(kCFAllocatorDefault, 
(CFURLRef)fileURL, NULL);
-            shouldUpdate = basePath != nil && refURL != nil;
-        }
-        
-        if (refURL == nil && basePath && relativePath) {
-            NSURL *aURL = [NSURL fileURLWithPath:[relativePath isAbsolutePath] 
? relativePath : [basePath stringByAppendingPathComponent:relativePath] 
isDirectory:NO];
-            refURL = (NSURL *)CFURLCreateFileReferenceURL(kCFAllocatorDefault, 
(CFURLRef)aURL, NULL);
-            shouldUpdate = refURL != nil;
-        }
-        
-        if (refURL == nil) {
-            if ([alias isKindOfClass:[NSData class]]) {
-                NSURL *aURL = (NSURL 
*)CFURLCreateByResolvingBookmarkData(kCFAllocatorDefault, (CFDataRef)alias, 
kCFURLBookmarkResolutionWithoutUIMask | 
kCFURLBookmarkResolutionWithoutMountingMask, NULL, NULL, (Boolean 
*)&shouldUpdate, NULL);
-                if (aURL) {
-                    refURL = (NSURL 
*)CFURLCreateFileReferenceURL(kCFAllocatorDefault, (CFURLRef)aURL, NULL);
-                    [aURL release];
-                }
-                shouldUpdate = shouldUpdate && basePath != nil && refURL != 
nil;
-            } else if ([alias isKindOfClass:[BDSKAlias class]]) {
-                FSRef aRef, baseRef;
-                BOOL ignored, hasBaseRef = BDSKPathToFSRef(basePath, &baseRef);
-                if ([alias getFSRef:&aRef baseRef:hasBaseRef ? &baseRef : NULL 
shouldUpdate:&ignored]){
-                    NSURL *aURL = BDSKCreateURLFromFSRef(&aRef);
-                    if (aURL) {
-                        refURL = (NSURL 
*)CFURLCreateFileReferenceURL(kCFAllocatorDefault, (CFURLRef)aURL, NULL);
-                        [aURL release];
-                    }
-                }
-                shouldUpdate = hasBaseRef && refURL != nil;
-            }
-        }
-        
-        if (refURL != nil) {
-            [fileRefURL release];
-            fileRefURL = refURL;
-        }
-    } else if (relativePath == nil) {
-        shouldUpdate = basePath != nil;
+- (BOOL)hasSkimNotes {
+    if (hasSkimNotesNeedsUpdate) {
+        hasSkimNotes = [[fileURL SkimNotes] count] > 0;
+        hasSkimNotesNeedsUpdate = NO;
     }
-    
-    if ((shouldUpdate || fileURL == nil) && fileRefURL != nil) {
-        NSURL *aURL = (NSURL *)CFURLCreateFilePathURL(kCFAllocatorDefault, 
(CFURLRef)fileRefURL, NULL);
-        if (aURL != nil) {
-            if (fileURL == nil)
-                fileURL = [aURL retain];
-            if (shouldUpdate) {
-                [self updateBookmark];
-                [self setRelativePath:[aURL path] fromPath:basePath];
-            }
-            [aURL release];
-        }
-    }
+    return hasSkimNotes;
 }
 
-- (void)updateFileURL {
-    BOOL hadFileURL = fileURL != nil;
-    NSURL *aURL = nil;
+- (NSData *)copyAliasDataRelativeToPath:(NSString *)basePath {
+    BDSKAlias *anAlias = NULL;
+    NSData *data = nil;
     
-    if (fileRefURL != nil) {
-        aURL = (NSURL *)CFURLCreateFilePathURL(kCFAllocatorDefault, 
(CFURLRef)fileRefURL, NULL);
-        if (aURL == nil)
-            // fileRefURL was invalid, try to update it
-            BDSKDESTROY(fileRefURL);
+    if (wantsBookmark && fileURL) {
+        anAlias = [BDSKAlias newWithPath:[fileURL path] basePath:basePath];
+    } else if (wantsBookmark == NO && fileRef) {
+        FSRef baseRef;
+        BOOL hasBaseRef = BDSKPathToFSRef(basePath, &baseRef);
+        anAlias = [BDSKAlias newWithFSRef:[fileRef fsRef] baseRef:hasBaseRef ? 
&baseRef : NULL];
+    } else if (relativePath && basePath) {
+        NSString *path = [relativePath isAbsolutePath] ? relativePath : 
[[basePath stringByAppendingPathComponent:relativePath] 
stringByStandardizingPath];
+        anAlias = [BDSKAlias newWithPath:path basePath:basePath];
     }
-    if (aURL == nil) {
-        // fileRefURL was nil or invalid
-        [self updateFileRefURL];
-        if (fileRefURL != nil)
-            aURL = (NSURL *)CFURLCreateFilePathURL(kCFAllocatorDefault, 
(CFURLRef)fileRefURL, NULL);
+    if (anAlias != NULL) {
+        data = [anAlias copyData];
+        [anAlias release];
+    } else if ([alias isKindOfClass:[BDSKAlias class]]) {
+        data = [alias copyData];
     }
     
-    if ([aURL isEqual:fileURL] == NO && (aURL != nil || hadFileURL)) {
-        // using bookmark and NSURL
-        NSURL *refURL = (NSURL 
*)CFURLCreateFileReferenceURL(kCFAllocatorDefault, (CFURLRef)fileURL, NULL);
-        if (refURL) {
-            // the file was replaced, reference the replacement rather than 
the moved file
-            // this is what Dropbox does with file updates
-            [fileRefURL release];
-            fileRefURL = refURL;
-            [aURL release];
-            aURL = (NSURL *)CFURLCreateFilePathURL(kCFAllocatorDefault, 
(CFURLRef)fileRefURL, NULL);
-            NSString *basePath = [delegate basePathForLinkedFile:self];
-            if (basePath) {
-                [self updateBookmark];
-                [self setRelativePath:[aURL path] fromPath:basePath];
-            }
-        }
-        [self setFileURL:aURL];
-    }
-    [aURL release];
-    isInitial = NO;
+    return data;
 }
 
 - (NSData *)copyBookmarkDataRelativeToPath:(NSString *)basePath {
@@ -1032,27 +771,52 @@
     return data;
 }
 
-- (NSData *)copyDataRelativeToPath:(NSString *)newBasePath isBookmark:(BOOL 
*)isBookmark {
-    NSData *data = [self copyBookmarkDataRelativeToPath:newBasePath];
-    if (data) {
-        *isBookmark = YES;
-    } else if ([alias isKindOfClass:[BDSKAlias class]]) {
-        data = [alias copyData];
-        *isBookmark = NO;
+- (NSString *)stringRelativeToPath:(NSString *)newBasePath {
+    BOOL noAlias = saveRelativePathOnly && newBasePath != nil;
+    if (newBasePath == nil)
+        newBasePath = [delegate basePathForLinkedFile:self];
+    // this will make sure the fileRef is valid
+    NSString *path = [self path];
+    NSData *data = nil;
+    NSString *dataKey = ALIASDATA_KEY;
+    path = path && newBasePath ? [path relativePathFromPath:newBasePath] : 
relativePath;
+    if (noAlias == NO || path == nil) {
+        if (wantsBookmark) {
+            data = [self copyBookmarkDataRelativeToPath:newBasePath];
+            if (data)
+                dataKey = BOOKMARK_KEY;
+            else if ([alias isKindOfClass:[BDSKAlias class]])
+                data = [alias copyData];
+        } else {
+            data = [self copyAliasDataRelativeToPath:newBasePath];
+            if (data == nil && [alias isKindOfClass:[NSData class]]) {
+                data = [alias retain];
+                dataKey = BOOKMARK_KEY;
+            }
+        }
     }
-    return data;
+    NSDictionary *dictionary = data ? [NSDictionary 
dictionaryWithObjectsAndKeys:data, dataKey, path, RELATIVEPATH_KEY, nil] : 
[NSDictionary dictionaryWithObjectsAndKeys:path, RELATIVEPATH_KEY, nil];
+    [data release];
+    if (saveArchivedData)
+        return [[NSKeyedArchiver archivedDataWithRootObject:dictionary] 
base64String];
+    else
+        return [[NSPropertyListSerialization dataWithPropertyList:dictionary 
format:NSPropertyListBinaryFormat_v1_0 options:0 error:NULL] base64String];
 }
 
-- (void)setBookmarkWithPath:(NSString *)aPath {
-    id anAlias = BDSKCreateBookmarkDataFromURL([NSURL fileURLWithPath:aPath]);
+- (void)setAliasOrBookmarkWithPath:(NSString *)aPath basePath:(NSString 
*)basePath {
+    id anAlias = nil;
+    if (wantsBookmark)
+        anAlias = BDSKCreateBookmarkDataFromURL([NSURL fileURLWithPath:aPath]);
+    else
+        anAlias = [BDSKAlias newWithPath:aPath basePath:basePath];
     if (anAlias != nil) {
         id saveAlias = alias;
         alias = anAlias;
-        [self updateFileRefURL];
-        if (fileRefURL == nil) {
+        [self updateFileRef];
+        if (fileRef == nil) {
             [anAlias release];
             alias = saveAlias;
-            [self updateFileRefURL];
+            [self updateFileRef];
         } else {
             [saveAlias release];
         }
@@ -1064,25 +828,33 @@
 - (void)updateWithPath:(NSString *)aPath {
     NSString *basePath = [delegate basePathForLinkedFile:self];
     
-    if (fileRefURL == nil) {
+    if (fileRef == nil) {
         // this does the updating if possible
-        [self updateFileRefURL];
+        [self updateFileRef];
     } else {
-        NSURL *aURL = (NSURL *)CFURLCreateFilePathURL(kCFAllocatorDefault, 
(CFURLRef)fileRefURL, NULL);
+        NSURL *aURL = [self newPathURL];
         if (aURL != nil) {
             // if the path has changed, updating will be done below
             if (basePath && (aPath == nil || [[aURL path] 
isEqualToString:aPath])) {
-                [self updateBookmark];
-                [self setRelativePath:[aURL path] fromPath:basePath];
+                if (wantsBookmark) {
+                    [self updateBookmark];
+                    [self setRelativePath:[aURL path] fromPath:basePath];
+                } else {
+                    FSRef baseRef;
+                    if (BDSKPathToFSRef(basePath, &baseRef)) {
+                        [self updateAliasWithBaseRef:&baseRef];
+                        [self setRelativePath:[aURL path] fromPath:basePath];
+                    }
+                }
             }
             [aURL release];
         } else {
-            // the fileRefURL was invalid, reset it and update
-            BDSKDESTROY(fileRefURL);
-            [self updateFileRefURL];
-            if (fileRefURL == nil && aPath) {
+            // the fileRef was invalid, reset it and update
+            BDSKDESTROY(fileRef);
+            [self updateFileRef];
+            if (fileRef == nil && aPath) {
                 // this can happen after an auto file to a volume, as the file 
is actually not moved but copied
-                [self setBookmarkWithPath:aPath];
+                [self setAliasOrBookmarkWithPath:aPath basePath:basePath];
                 if (basePath)
                     [self setRelativePath:aPath fromPath:basePath];
             }
@@ -1092,31 +864,63 @@
         NSString *path = [self path];
         if ([path isEqualToString:aPath] == NO) {
             BOOL needsUpdate = YES;
-            NSURL *refURL = (NSURL 
*)CFURLCreateFileReferenceURL(kCFAllocatorDefault, (CFURLRef)[NSURL 
fileURLWithPath:aPath], NULL);
-            if (refURL) {
-                NSURL *aURL = (NSURL 
*)CFURLCreateFilePathURL(kCFAllocatorDefault, (CFURLRef)refURL, NULL);
-                if ([path isEqualToString:[aURL path]]) {
-                    [refURL release];
-                    needsUpdate = NO;
-                } else {
-                    [fileRefURL release];
-                    fileRefURL = refURL;
-                    [self setFileURL:aURL];
+            if (wantsBookmark) {
+                // using bookmark and NSURL
+                NSURL *refURL = (NSURL 
*)CFURLCreateFileReferenceURL(kCFAllocatorDefault, (CFURLRef)[NSURL 
fileURLWithPath:aPath], NULL);
+                if (refURL) {
+                    NSURL *aURL = (NSURL 
*)CFURLCreateFilePathURL(kCFAllocatorDefault, (CFURLRef)refURL, NULL);
+                    if ([path isEqualToString:[aURL path]]) {
+                        [refURL release];
+                        needsUpdate = NO;
+                    } else {
+                        [fileRef release];
+                        fileRef = refURL;
+                        [self setFileURL:aURL];
+                    }
+                    [aURL release];
                 }
-                [aURL release];
-            }
-            if (needsUpdate) {
-                if (basePath) {
-                    [self updateBookmark];
-                    [self setRelativePath:aPath fromPath:basePath];
-                } else {
-                    [self setBookmarkWithPath:aPath];
+                if (needsUpdate) {
+                    if (basePath) {
+                        [self updateBookmark];
+                        [self setRelativePath:aPath fromPath:basePath];
+                    } else {
+                        [self setAliasOrBookmarkWithPath:aPath 
basePath:basePath];
+                    }
                 }
+            } else {
+                // using AliasHandle and FSRef
+                FSRef aRef;
+                if (BDSKPathToFSRef(aPath, &aRef)) {
+                    NSURL *aURL = BDSKCreateURLFromFSRef(&aRef);
+                    if ([path isEqualToString:[aURL path]]) {
+                        needsUpdate = NO;
+                    } else {
+                        [fileRef release];
+                        fileRef = [[BDSKFileRef alloc] initWithFSRef:&aRef];
+                        [self setFileURL:aURL];
+                    }
+                    [aURL release];
+                }
+                if (needsUpdate) {
+                    FSRef baseRef;
+                    if (BDSKPathToFSRef(basePath, &baseRef)) {
+                        [self updateAliasWithBaseRef:&baseRef];
+                        [self setRelativePath:aPath fromPath:basePath];
+                    } else {
+                        [self setAliasOrBookmarkWithPath:aPath 
basePath:basePath];
+                    }
+                }
             }
         }
     }
 }
 
+- (void)updateHasSkimNotes {
+    hasSkimNotesNeedsUpdate = YES;
+    if (isInitial == NO)
+        [delegate performSelector:@selector(linkedFileURLChanged:) 
withObject:self afterDelay:0.0];
+}
+
 @end
 
 #pragma mark -

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