Revision: 26846
          http://sourceforge.net/p/bibdesk/svn/26846
Author:   hofman
Date:     2021-09-11 17:59:22 +0000 (Sat, 11 Sep 2021)
Log Message:
-----------
Move alias and bookmark based linked file to separate subclasses of 
BDSKLinkedAliasFile. Redirect (un)archivers to the correct classes. 
Implementation based methods, such as URL and reference updating, are done in 
the subclasses, generic methods in BDSKLinkedAliasFile. Let bookmarked based 
class use path based fileURL as primary reference, and the file reference URL 
as secondary to find back moved files or notice replacements.

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

Modified: trunk/bibdesk/BDSKLinkedFile.m
===================================================================
--- trunk/bibdesk/BDSKLinkedFile.m      2021-09-11 14:09:28 UTC (rev 26845)
+++ trunk/bibdesk/BDSKLinkedFile.m      2021-09-11 17:59:22 UTC (rev 26846)
@@ -74,15 +74,6 @@
 
 #pragma mark -
 
-@interface BDSKFileRef : NSObject {
-    const FSRef *fsRef;
-}
-- (id)initWithFSRef:(FSRef *)aRef;
-@property (nonatomic, readonly) const FSRef *fsRef;
-@end
-
-#pragma mark -
-
 // Private placeholder subclass
 
 @interface BDSKPlaceholderLinkedFile : BDSKLinkedFile
@@ -94,7 +85,6 @@
 
 @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;
@@ -102,13 +92,24 @@
     BOOL hasSkimNotesNeedsUpdate;
     id delegate;
 }
+- (void)updateFileURL;
+- (NSData *)copyAliasDataRelativeToPath:(NSString *)newBasePath;
+@end
 
+#pragma mark -
+
+@interface BDSKAliasLinkedFile : BDSKLinkedAliasFile {
+    const FSRef *fileRef;
+}
 - (void)updateFileRef;
-- (void)updateFileURL;
+@end
 
-- (NSData *)copyAliasDataRelativeToPath:(NSString *)newBasePath;
+#pragma mark -
+
+@interface BDSKBookmarkLinkedFile : BDSKLinkedAliasFile {
+    NSURL *fileRefURL;
+}
 - (NSData *)copyBookmarkDataRelativeToPath:(NSString *)newBasePath;
-
 @end
 
 #pragma mark -
@@ -139,6 +140,10 @@
     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 {
@@ -246,7 +251,7 @@
 
 - (id)initWithURL:(NSURL *)aURL delegate:(id<BDSKLinkedFileDelegate>)aDelegate 
{
     if([aURL isFileURL])
-        return (id)[[BDSKLinkedAliasFile alloc] initWithURL:aURL 
delegate:aDelegate];
+        return (id)[(wantsBookmark ? [BDSKBookmarkLinkedFile alloc] : 
[BDSKAliasLinkedFile alloc]) initWithURL:aURL delegate:aDelegate];
     else if (aURL)
         return (id)[[BDSKLinkedURL alloc] initWithURL:aURL delegate:aDelegate];
     else
@@ -254,7 +259,7 @@
 }
 
 - (id)initWithBase64String:(NSString *)base64String 
delegate:(id<BDSKLinkedFileDelegate>)aDelegate {
-    return (id)[[BDSKLinkedAliasFile alloc] initWithBase64String:base64String 
delegate:aDelegate];
+    return (id)[(wantsBookmark ? [BDSKBookmarkLinkedFile alloc] : 
[BDSKAliasLinkedFile alloc]) initWithBase64String:base64String 
delegate:aDelegate];
 }
 
 - (id)initWithURLString:(NSString *)aString {
@@ -287,7 +292,6 @@
     } 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;
@@ -301,24 +305,8 @@
 }
 
 - (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;
-    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;
+    BDSKASSERT_NOT_REACHED("Attempt to initialize BDSKLinkedAliasFile directly 
with a URL");
+    return nil;
 }
 
 - (id)initWithBase64String:(NSString *)base64String 
delegate:(id<BDSKLinkedFileDelegate>)aDelegate {
@@ -385,6 +373,11 @@
 }
 
 - (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]) {
@@ -404,33 +397,23 @@
 - (void)encodeWithCoder:(NSCoder *)coder {
     // make sure the fileRef is valid
     [self updateFileURL];
-    NSData *data = nil;
-    NSString *basePath = [delegate basePathForLinkedFile:self];
     if ([coder allowsKeyedCoding]) {
-        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];
-        }
+        // the alias or bookmark data is set by the subclasses
         [coder encodeObject:relativePath forKey:RELATIVEPATH_KEY];
     } else {
-        data = [self copyAliasDataRelativeToPath:basePath];
+        NSData *data = [self copyAliasDataRelativeToPath:[delegate 
basePathForLinkedFile:self]];
         [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);
@@ -440,21 +423,11 @@
 - (id)copyWithZone:(NSZone *)aZone {
     // make sure the fileRef is valid
     [self updateFileURL];
-    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];
-    }
+    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;
@@ -499,25 +472,179 @@
     }
 }
 
-- (NSURL *)newPathURL {
-    if (fileRef == nil)
-        return nil;
-    else if (wantsBookmark)
-        return (NSURL *)CFURLCreateFilePathURL(kCFAllocatorDefault, 
(CFURLRef)fileRef, NULL);
+// 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];
     else
-        return BDSKCreateURLFromFSRef([fileRef fsRef]);
+        return [[NSPropertyListSerialization dataWithPropertyList:dictionary 
format:NSPropertyListBinaryFormat_v1_0 options:0 error:NULL] base64String];
 }
 
+// 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 fsRef] baseRef:baseRef];
+        [alias updateWithFSRef:fileRef baseRef:baseRef];
     } else {
-        BDSKAlias *anAlias = [BDSKAlias newWithFSRef:[fileRef fsRef] 
baseRef:baseRef];
+        BDSKAlias *anAlias = [BDSKAlias newWithFSRef:fileRef baseRef:baseRef];
         if (anAlias) {
             BDSKDESTROY(alias);
             alias = anAlias;
@@ -525,130 +652,55 @@
     }
 }
 
-- (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;
     
-    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;
+    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 ((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 && hasBaseRef && relativePath) {
+            NSString *path = [relativePath isAbsolutePath] ? relativePath : 
[basePath stringByAppendingPathComponent:relativePath];
+            shouldUpdate = hasRef = BDSKPathToFSRef(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);
+        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 == 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 ((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];
+        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];
             }
+            [aURL release];
         }
     }
 }
@@ -658,51 +710,31 @@
     NSURL *aURL = nil;
     
     if (fileRef != nil) {
-        aURL = [self newPathURL];
+        aURL = BDSKCreateURLFromFSRef(fileRef);
         if (aURL == nil)
             // fileRef was invalid, try to update it
-            BDSKDESTROY(fileRef);
+            BDSKZONEDESTROY(fileRef);
     }
     if (aURL == nil) {
         // fileRef was nil or invalid
         [self updateFileRef];
-        aURL = [self newPathURL];
+        aURL = BDSKCreateURLFromFSRef(fileRef);
     }
     
     if ([aURL isEqual:fileURL] == NO && (aURL != nil || hadFileURL)) {
-        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];
-                }
+        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];
             }
-        } else {
-            // using AliasHandle and FSRef
-            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
-                [fileRef release];
-                fileRef = [[BDSKFileRef alloc] initWithFSRef:&aRef];
-                [aURL release];
-                aURL = [self newPathURL];
-                NSString *basePath = [delegate basePathForLinkedFile:self];
-                FSRef baseRef;
-                if (BDSKPathToFSRef(basePath, &baseRef)) {
-                    [self updateAliasWithBaseRef:&baseRef];
-                    [self setRelativePath:[aURL path] fromPath:basePath];
-                }
-            }
         }
         [self setFileURL:aURL];
     }
@@ -710,38 +742,14 @@
     isInitial = NO;
 }
 
-- (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 (wantsBookmark && fileURL) {
-        anAlias = [BDSKAlias newWithPath:[fileURL path] basePath:basePath];
-    } else if (wantsBookmark == NO && fileRef) {
+    if (fileRef) {
         FSRef baseRef;
         BOOL hasBaseRef = BDSKPathToFSRef(basePath, &baseRef);
-        anAlias = [BDSKAlias newWithFSRef:[fileRef fsRef] baseRef:hasBaseRef ? 
&baseRef : NULL];
+        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];
@@ -756,59 +764,8 @@
     return data;
 }
 
-- (NSData *)copyBookmarkDataRelativeToPath:(NSString *)basePath {
-    NSData *data = nil;
-    
-    if (fileURL) {
-        data = BDSKCreateBookmarkDataFromURL(fileURL);
-    } else if (relativePath && basePath) {
-        NSURL *aURL = [NSURL fileURLWithPath:[relativePath isAbsolutePath] ? 
relativePath : [[basePath stringByAppendingPathComponent:relativePath] 
stringByStandardizingPath]];
-        data = BDSKCreateBookmarkDataFromURL(aURL);
-    }
-    if (data == nil && [alias isKindOfClass:[NSData class]])
-        data = [alias copy];
-    
-    return data;
-}
-
-- (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;
-            }
-        }
-    }
-    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)setAliasOrBookmarkWithPath:(NSString *)aPath basePath:(NSString 
*)basePath {
-    id anAlias = nil;
-    if (wantsBookmark)
-        anAlias = BDSKCreateBookmarkDataFromURL([NSURL fileURLWithPath:aPath]);
-    else
-        anAlias = [BDSKAlias newWithPath:aPath basePath:basePath];
+- (void)setAliasWithPath:(NSString *)aPath basePath:(NSString *)basePath {
+    id anAlias = [BDSKAlias newWithPath:aPath basePath:basePath];
     if (anAlias != nil) {
         id saveAlias = alias;
         alias = anAlias;
@@ -832,29 +789,24 @@
         // this does the updating if possible
         [self updateFileRef];
     } else {
-        NSURL *aURL = [self newPathURL];
+        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])) {
-                if (wantsBookmark) {
-                    [self updateBookmark];
+                FSRef baseRef;
+                if (BDSKPathToFSRef(basePath, &baseRef)) {
+                    [self updateAliasWithBaseRef:&baseRef];
                     [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 fileRef was invalid, reset it and update
-            BDSKDESTROY(fileRef);
+            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 setAliasOrBookmarkWithPath:aPath basePath:basePath];
+                [self setAliasWithPath:aPath basePath:basePath];
                 if (basePath)
                     [self setRelativePath:aPath fromPath:basePath];
             }
@@ -864,63 +816,238 @@
         NSString *path = [self path];
         if ([path isEqualToString:aPath] == NO) {
             BOOL needsUpdate = YES;
-            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];
+            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 (needsUpdate) {
-                    if (basePath) {
-                        [self updateBookmark];
-                        [self setRelativePath:aPath fromPath:basePath];
-                    } else {
-                        [self setAliasOrBookmarkWithPath:aPath 
basePath:basePath];
-                    }
+                [aURL release];
+            }
+            if (needsUpdate) {
+                FSRef baseRef;
+                if (BDSKPathToFSRef(basePath, &baseRef)) {
+                    [self updateAliasWithBaseRef:&baseRef];
+                    [self setRelativePath:aPath fromPath:basePath];
+                } else {
+                    [self setAliasWithPath: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];
+            }
+        }
+    }
+}
+
+@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 updateFileURL];
+    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
+    [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;
+}
+
+- (void)updateFileURL {
+    NSString *basePath = nil;
+    BOOL shouldUpdate = NO;
+    NSURL *aURL = nil;
+    NSURL *refURL = nil;
+    
+    if (fileURL) {
+        refURL = (NSURL *)CFURLCreateFileReferenceURL(kCFAllocatorDefault, 
(CFURLRef)fileURL, NULL);
+        
+        if (refURL == nil) {
+            // fileURL was invalid, try to update it
+            BDSKDESTROY(fileURL);
+        } else if ([fileRefURL isEqual:refURL] == NO) {
+            // file was replaced
+            [fileRefURL release];
+            fileRefURL = refURL;
+            hasSkimNotesNeedsUpdate = YES;
+            if (isInitial)
+                [delegate linkedFileURLChanged:self];
+            basePath = [delegate basePathForLinkedFile:self];
+            shouldUpdate = YES;
+        } else {
+            BDSKDESTROY(refURL);
+            if (relativePath == nil) {
+                basePath = [delegate basePathForLinkedFile:self];
+                shouldUpdate = YES;
+            }
+        }
+    }
+    
+    if (fileURL == nil) {
+        
+        if (fileRefURL) {
+            aURL = (NSURL *)CFURLCreateFilePathURL(kCFAllocatorDefault, 
(CFURLRef)fileRefURL, NULL);
+            shouldUpdate = aURL != nil;
+        }
+        
+        basePath = [delegate basePathForLinkedFile:self];
+        
+        if (aURL == nil && basePath && relativePath) {
+            aURL = [[NSURL alloc] initFileURLWithPath:[relativePath 
isAbsolutePath] ? relativePath : [basePath 
stringByAppendingPathComponent:relativePath] isDirectory:NO];
+            refURL = (NSURL *)CFURLCreateFileReferenceURL(kCFAllocatorDefault, 
(CFURLRef)aURL, NULL);
+            shouldUpdate = refURL != nil;
+        }
+        
+        if (refURL == nil && [alias isKindOfClass:[NSData class]]) {
+            aURL = (NSURL 
*)CFURLCreateByResolvingBookmarkData(kCFAllocatorDefault, (CFDataRef)alias, 
kCFURLBookmarkResolutionWithoutUIMask | 
kCFURLBookmarkResolutionWithoutMountingMask, NULL, NULL, (Boolean 
*)&shouldUpdate, NULL);
+            if (aURL)
+                refURL = (NSURL 
*)CFURLCreateFileReferenceURL(kCFAllocatorDefault, (CFURLRef)aURL, NULL);
+            shouldUpdate = shouldUpdate && aURL != nil;
+        } else if (aURL == nil && [alias isKindOfClass:[BDSKAlias class]]) {
+            FSRef aRef, baseRef;
+            BOOL ignored, hasBaseRef = BDSKPathToFSRef(basePath, &baseRef);
+            if ([alias getFSRef:&aRef baseRef:hasBaseRef ? &baseRef : NULL 
shouldUpdate:&ignored]){
+                aURL = BDSKCreateURLFromFSRef(&aRef);
+                if (aURL)
+                    refURL = (NSURL 
*)CFURLCreateFileReferenceURL(kCFAllocatorDefault, (CFURLRef)aURL, NULL);
+            }
+            shouldUpdate = aURL != nil;
+        }
+        
+        if (aURL) {
+            [self setFileURL:aURL];
+            if (refURL) {
+                [fileRefURL release];
+                fileRefURL = refURL;
+            }
+            [aURL release];
+        } else {
+            BDSKDESTROY(fileRefURL);
+        }
+    }
+    
+    if (shouldUpdate) {
+        NSData *data = BDSKCreateBookmarkDataFromURL(fileURL ?: [fileRefURL 
filePathURL]);
+        if (data) {
+            [alias release];
+            alias = data;
+        }
+        if (basePath)
+            [self setRelativePath:[fileURL path] fromPath:basePath];
+    }
+}
+
+- (NSData *)copyBookmarkDataRelativeToPath:(NSString *)basePath {
+    NSData *data = nil;
+    
+    if (fileURL) {
+        data = BDSKCreateBookmarkDataFromURL(fileURL);
+    } else if (relativePath && basePath) {
+        NSURL *aURL = [NSURL fileURLWithPath:[relativePath isAbsolutePath] ? 
relativePath : [[basePath stringByAppendingPathComponent:relativePath] 
stringByStandardizingPath]];
+        data = BDSKCreateBookmarkDataFromURL(aURL);
+    }
+    if (data == nil && [alias isKindOfClass:[NSData class]])
+        data = [alias copy];
+    
+    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;
+    }
+    return data;
+}
+
+// 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 (aPath) {
+        // this implicitly calls updateFileURL
+        NSString *path = [self path];
+        if ([path isEqualToString:aPath] == NO) {
+            // this can happen when auto filing to a different volume, which 
copies the file
+            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 (needsUpdate) {
-                    FSRef baseRef;
-                    if (BDSKPathToFSRef(basePath, &baseRef)) {
-                        [self updateAliasWithBaseRef:&baseRef];
-                        [self setRelativePath:aPath fromPath:basePath];
-                    } else {
-                        [self setAliasOrBookmarkWithPath:aPath 
basePath:basePath];
-                    }
+                [aURL release];
+            }
+            if (needsUpdate) {
+                NSData *data = BDSKCreateBookmarkDataFromURL(fileURL ?: 
[fileRefURL filePathURL]);
+                if (data) {
+                    [alias release];
+                    alias = data;
                 }
+                if (basePath)
+                    [self setRelativePath:aPath fromPath:basePath];
             }
         }
+    } else {
+        // this does the updating of the bookmark and URLs if needed
+        [self updateFileURL];
+        if (fileURL && basePath) {
+            // the basePath may have changed, which may be noted by 
updateFileURL
+            [self setRelativePath:[fileURL path] fromPath:basePath];
+        }
     }
 }
 
-- (void)updateHasSkimNotes {
-    hasSkimNotesNeedsUpdate = YES;
-    if (isInitial == NO)
-        [delegate performSelector:@selector(linkedFileURLChanged:) 
withObject:self afterDelay:0.0];
-}
-
 @end
 
 #pragma mark -
@@ -1155,36 +1282,3 @@
 #pragma clang diagnostic pop
 
 @end
-
-#pragma mark -
-
-@implementation BDSKFileRef
-
-@synthesize fsRef;
-
-- (id)initWithFSRef:(FSRef *)aRef {
-    if (aRef == NULL) {
-        [self release];
-        self = nil;
-    } else {
-        self = [super init];
-        if (self) {
-            FSRef *newRef = (FSRef *)NSZoneMalloc([self zone], sizeof(FSRef));
-            if (newRef) {
-                bcopy(aRef, newRef, sizeof(FSRef));
-                fsRef = newRef;
-            } else {
-                [self release];
-                self = nil;
-            }
-        }
-    }
-    return self;
-}
-
-- (void)dealloc {
-    BDSKZONEDESTROY(fsRef);
-    [super dealloc];
-}
-
-@end

Modified: trunk/bibdesk/BibDocument.m
===================================================================
--- trunk/bibdesk/BibDocument.m 2021-09-11 14:09:28 UTC (rev 26845)
+++ trunk/bibdesk/BibDocument.m 2021-09-11 17:59:22 UTC (rev 26846)
@@ -190,6 +190,12 @@
 @synthesize documentWindow, tableView, splitView, mainBox, mainView, 
controlContentView, statusBar, groupOutlineView, groupSplitView, 
groupActionButton, groupAddButton, groupButtonView, groupFieldMenu, 
sidePreviewTabView, sidePreviewTextView, sideFileView, sidePreviewButton, 
sidePreviewButtonView, bottomPreviewTabView, bottomPreviewTextView, 
bottomFileView, bottomPreviewButton, actionMenuButton, groupActionMenuButton, 
searchField, groupMenu, actionMenu, alternateCopyMenu, sharingMenu, 
publications, shownPublications, groups, documentInfo, macroResolver;
 @dynamic mainWindowSetupDictionaryFromExtendedAttributes, mainDocument, 
atomData, MODSData, endNoteData, wordXMLData, numberOfSelectedPubs, 
numberOfClickedOrSelectedPubs, selectedPublications, 
clickedOrSelectedPublications, singleSelectedPublication, selectedFileURLs, 
clickedOrSelectedFileURLs, selectedRemoteURLs, clickedOrSelectedRemoteURLs, 
documentStringEncoding, sharingServices;
 
++ (void)initialize {
+    BDSKINITIALIZE;
+    // make sure the unarchiver redirects are installed
+    [BDSKLinkedFile class];
+}
+
 + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
     NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
     if ([key isEqualToString:@"displayName"])

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