Revision: 29323
          http://sourceforge.net/p/bibdesk/svn/29323
Author:   hofman
Date:     2025-07-22 14:24:08 +0000 (Tue, 22 Jul 2025)
Log Message:
-----------
register ietms for crossref key by publications array so we can quickly look 
them up

Modified Paths:
--------------
    trunk/bibdesk/BDSKPublicationsArray.h
    trunk/bibdesk/BDSKPublicationsArray.m
    trunk/bibdesk/BibDocument_UI.m
    trunk/bibdesk/BibItem.m

Modified: trunk/bibdesk/BDSKPublicationsArray.h
===================================================================
--- trunk/bibdesk/BDSKPublicationsArray.h       2025-07-22 09:07:22 UTC (rev 
29322)
+++ trunk/bibdesk/BDSKPublicationsArray.h       2025-07-22 14:24:08 UTC (rev 
29323)
@@ -45,6 +45,7 @@
 @interface BDSKPublicationsArray : NSMutableArray {
     NSMutableArray *publications;
     NSMapTable *itemsForCiteKeys;
+    NSMapTable *itemsForCrossrefs;
     NSMutableDictionary *itemsForIdentifierURLs;
     BDSKItemSearchIndexes *searchIndexes;
 }
@@ -59,6 +60,9 @@
 - (nullable NSArray *)allItemsForCiteKey:(NSString *)key;
 - (void)changeCiteKey:(NSString *)oldKey toCiteKey:(NSString *)newKey 
forItem:(BibItem *)anItem;
 
+- (nullable NSArray *)allItemsForCrossref:(NSString *)key;
+- (void)changeCrossref:(nullable NSString *)oldKey toCrossref:(nullable 
NSString *)newKey forItem:(BibItem *)anItem;
+
 - (nullable BibItem *)itemForIdentifierURL:(NSURL *)aURL;
 - (nullable NSArray *)itemsForIdentifierURLs:(NSArray *)anArray;
 

Modified: trunk/bibdesk/BDSKPublicationsArray.m
===================================================================
--- trunk/bibdesk/BDSKPublicationsArray.m       2025-07-22 09:07:22 UTC (rev 
29322)
+++ trunk/bibdesk/BDSKPublicationsArray.m       2025-07-22 14:24:08 UTC (rev 
29323)
@@ -48,12 +48,14 @@
 
 
 @interface BDSKPublicationsArray ()
-- (instancetype)initTemporaryWithArray:(NSArray *)anArray 
itemsForCiteKey:(NSMapTable *)anItemsForCiteKey NS_DESIGNATED_INITIALIZER;
+- (instancetype)initTemporaryWithArray:(NSArray *)anArray 
itemsForCiteKey:(NSMapTable *)citeKeyMapTable itemsForCrossrefs:(NSMapTable 
*)crossrefMapTable NS_DESIGNATED_INITIALIZER;
 @end
 
 @interface BDSKPublicationsArray (Private)
 - (void)addItem:(BibItem *)item forCiteKey:(NSString *)key;
 - (void)removeItem:(BibItem *)item forCiteKey:(NSString *)key;
+- (void)addItem:(BibItem *)item forCrossref:(NSString *)key;
+- (void)removeItem:(BibItem *)item forCrossref:(NSString *)key;
 - (void)addItem:(BibItem *)item;
 - (void)addItems:(NSArray *)items;
 - (void)removeItem:(BibItem *)item;
@@ -93,6 +95,7 @@
         NSPointerFunctions *keyPointerFunctions = [NSPointerFunctions 
caseInsensitiveStringPointerFunctions];
         NSPointerFunctions *valuePointerFunctions = [NSPointerFunctions 
strongObjectPointerFunctions];
         itemsForCiteKeys = [[NSMapTable alloc] 
initWithKeyPointerFunctions:keyPointerFunctions 
valuePointerFunctions:valuePointerFunctions capacity:0];
+        itemsForCrossrefs = [[NSMapTable alloc] 
initWithKeyPointerFunctions:keyPointerFunctions 
valuePointerFunctions:valuePointerFunctions capacity:0];
         searchIndexes = [[BDSKItemSearchIndexes alloc] init];
         if ([anArray count]) {
             [self addItems:publications];
@@ -107,18 +110,23 @@
     return self;
 }
 
-- (instancetype)initTemporaryWithArray:(NSArray *)anArray 
itemsForCiteKey:(NSMapTable *)mapTable
+- (instancetype)initTemporaryWithArray:(NSArray *)anArray 
itemsForCiteKey:(NSMapTable *)citeKeyMapTable itemsForCrossrefs:(NSMapTable 
*)crossrefMapTable
 {
     self = [super init];
     if (self) {
         publications = [[NSMutableArray alloc] initWithArray:anArray];
         itemsForIdentifierURLs = nil;
-        itemsForCiteKeys = [[NSMapTable alloc] 
initWithKeyPointerFunctions:[mapTable keyPointerFunctions] 
valuePointerFunctions:[mapTable valuePointerFunctions] capacity:0];
+        itemsForCiteKeys = [[NSMapTable alloc] 
initWithKeyPointerFunctions:[citeKeyMapTable keyPointerFunctions] 
valuePointerFunctions:[citeKeyMapTable valuePointerFunctions] capacity:0];
+        itemsForCrossrefs = [[NSMapTable alloc] 
initWithKeyPointerFunctions:[crossrefMapTable keyPointerFunctions] 
valuePointerFunctions:[crossrefMapTable valuePointerFunctions] capacity:0];
         searchIndexes = nil;
-        for (NSString *key in mapTable) {
-            NSMutableArray *value = [[mapTable objectForKey:key] mutableCopy];
+        for (NSString *key in citeKeyMapTable) {
+            NSMutableArray *value = [[citeKeyMapTable objectForKey:key] 
mutableCopy];
             [itemsForCiteKeys setObject:value forKey:key];
         }
+        for (NSString *key in crossrefMapTable) {
+            NSMutableArray *value = [[crossrefMapTable objectForKey:key] 
mutableCopy];
+            [itemsForCiteKeys setObject:value forKey:key];
+        }
     }
     return self;
 }
@@ -144,7 +152,7 @@
 }
 
 - (BDSKPublicationsArray *)copyTemporary {
-    return [[BDSKPublicationsArray alloc] initTemporaryWithArray:publications 
itemsForCiteKey:itemsForCiteKeys];
+    return [[BDSKPublicationsArray alloc] initTemporaryWithArray:publications 
itemsForCiteKey:itemsForCiteKeys itemsForCrossrefs:itemsForCrossrefs];
 }
 
 #pragma mark NSMutableArray primitive methods
@@ -211,6 +219,7 @@
 - (void)removeAllObjects{
     if ([publications count] == 0) return;
     [itemsForCiteKeys removeAllObjects];
+    [itemsForCrossrefs removeAllObjects];
     [publications removeAllObjects];
     [itemsForIdentifierURLs removeAllObjects];
     [searchIndexes reset];
@@ -270,6 +279,21 @@
     return items ?: @[];
 }
 
+#pragma mark Items for crossrefs
+
+- (void)changeCrossref:(NSString *)oldKey toCrossref:(NSString *)newKey 
forItem:(BibItem *)anItem {
+    if ([NSString isEmptyString:oldKey] == NO)
+        [self removeItem:anItem forCrossref:oldKey];
+    if ([NSString isEmptyString:newKey] == NO)
+        [self addItem:anItem forCrossref:newKey];
+}
+
+- (NSArray *)allItemsForCrossref:(NSString *)key {
+    if ([NSString isEmptyString:key] == NO)
+        return [itemsForCrossrefs objectForKey:key];
+    return nil;
+}
+
 #pragma mark Identifiers for Search and AppleScript
 
 - (BibItem *)itemForIdentifierURL:(NSURL *)aURL;
@@ -329,8 +353,32 @@
     }
 }
 
+- (void)addItem:(BibItem *)item forCrossref:(NSString *)key{
+    if ([NSString isEmptyString:key] == NO) {
+        NSMutableArray *array = [itemsForCrossrefs objectForKey:key];
+        if (array) {
+            [array addObject:item];
+        } else {
+            array = [[NSMutableArray alloc] initWithObjects:item, nil];
+            [itemsForCrossrefs setObject:array forKey:key];
+        }
+    }
+}
+
+- (void)removeItem:(BibItem *)item forCrossref:(NSString *)key{
+    if ([NSString isEmptyString:key] == NO) {
+        NSMutableArray *array = [itemsForCrossrefs objectForKey:key];
+        if (array) {
+            [array removeObject:item];
+            if ([array count] == 0)
+                [itemsForCrossrefs removeObjectForKey:key];
+        }
+    }
+}
+
 - (void)addItem:(BibItem *)item{
     [self addItem:item forCiteKey:[item citeKey]];
+    [self addItem:item forCrossref:[item valueOfField:BDSKCrossrefString 
inherit:NO]];
     [itemsForIdentifierURLs setObject:item forKey:[item identifierURL]];
     [searchIndexes addPublications:@[item]];
 }
@@ -338,6 +386,7 @@
 - (void)addItems:(NSArray *)items{
     for (BibItem *item in items) {
         [self addItem:item forCiteKey:[item citeKey]];
+        [self addItem:item forCrossref:[item valueOfField:BDSKCrossrefString 
inherit:NO]];
         [itemsForIdentifierURLs setObject:item forKey:[item identifierURL]];
     }
     [searchIndexes addPublications:items];
@@ -345,6 +394,7 @@
 
 - (void)removeItem:(BibItem *)item{
     [self removeItem:item forCiteKey:[item citeKey]];
+    [self removeItem:item forCrossref:[item valueOfField:BDSKCrossrefString 
inherit:NO]];
     [itemsForIdentifierURLs removeObjectForKey:[item identifierURL]];
     [searchIndexes removePublications:@[item]];
 }
@@ -352,6 +402,7 @@
 - (void)removeItems:(NSArray *)items{
     for (BibItem *item in items) {
         [self removeItem:item forCiteKey:[item citeKey]];
+        [self removeItem:item forCrossref:[item 
valueOfField:BDSKCrossrefString inherit:NO]];
         [itemsForIdentifierURLs removeObjectForKey:[item identifierURL]];
     }
     [searchIndexes removePublications:items];

Modified: trunk/bibdesk/BibDocument_UI.m
===================================================================
--- trunk/bibdesk/BibDocument_UI.m      2025-07-22 09:07:22 UTC (rev 29322)
+++ trunk/bibdesk/BibDocument_UI.m      2025-07-22 14:24:08 UTC (rev 29323)
@@ -1423,8 +1423,10 @@
     BOOL isEdit = [changedKey isNoteField] && [userInfo count] == 1;
     
     // when the crossref changes, all ionherited fields can change
-    if ([changedKey isEqualToString:BDSKCrossrefString])
+    if ([changedKey isEqualToString:BDSKCrossrefString]) {
+        [publications changeCrossref:[userInfo 
objectForKey:BDSKBibItemOldValueKey] toCrossref:[pub 
valueOfField:BDSKCrossrefString inherit:NO] forItem:pub];
         changedKey = nil;
+    }
     
     // need to handle cite keys and crossrefs if a cite key changed
     if([changedKey isEqualToString:BDSKCiteKeyString]){
@@ -1446,41 +1448,43 @@
                                                           userInfo:notifInfo];
     }
     
-    // access type manager outside the enumerator, since it's @synchronized...
-    NSCharacterSet *invalidSet = nil;
-    NSSet *citeFields = nil;
-    if (oldKey) {
-        BDSKTypeManager *typeManager = [BDSKTypeManager sharedManager];
-        invalidSet = [typeManager invalidCharactersForField:BDSKCiteKeyString];
-        citeFields = [typeManager citationFieldsSet];
-    }
-    
     if ([changedKey isNoteField] == NO && [changedKey isGeneralURLField] == NO 
&& [changedKey isIntegerField] == NO && [changedKey 
isEqualToString:BDSKPubTypeString] == NO) {
-        for (BibItem *aPub in publications) {
-            NSString *crossref = [aPub valueOfField:BDSKCrossrefString 
inherit:NO];
-            
+        NSArray *crossreffedItems = [publications allItemsForCrossref:key];
+        if ([crossreffedItems count]) {
             // invalidate groups that depend on inherited values
-            if ([NSString isEmptyString:crossref] == NO && [key 
isCaseInsensitiveEqual:crossref]) {
+            for (BibItem *aPub in crossreffedItems) {
                 [aPub resetGroups];
-                // inherited fields are also searched
                 if (shouldReindex)
                     [publications reindexPublication:aPub];
-                [changedPublications addObject:aPub];
-                // all inherited fields could change when parent is created, 
needs full UI update
-                if ([changedKey isEqualToString:BDSKCiteKeyString])
-                    changedKey = nil;
             }
+            [changedPublications addObject:crossreffedItems];
+            // all inherited fields could change when parent is created, needs 
full UI update
+            if ([changedKey isEqualToString:BDSKCiteKeyString])
+                changedKey = nil;
+        }
+        if (oldKey) {
+            // change the crossrefs if we change the parent cite key
+            crossreffedItems = [[publications allItemsForCrossref:oldKey] 
copy];
+            if ([crossreffedItems count]) {
+                for (BibItem *aPub in crossreffedItems)
+                    [aPub setField:BDSKCrossrefString toValue:key];
+            }
             
-            // change the crossrefs if we change the parent cite key
+            // access type manager outside the enumerator, since it's 
@synchronized...
+            NSCharacterSet *invalidSet = nil;
+            NSSet *citeFields = nil;
             if (oldKey) {
-                if ([oldKey isCaseInsensitiveEqual:crossref])
-                    [aPub setField:BDSKCrossrefString toValue:key];
-                
+                BDSKTypeManager *typeManager = [BDSKTypeManager sharedManager];
+                invalidSet = [typeManager 
invalidCharactersForField:BDSKCiteKeyString];
+                citeFields = [typeManager citationFieldsSet];
+            }
+            // change the key in the citation fields
+            for (BibItem *aPub in publications) {
                 for (NSString *field in citeFields) {
                     NSString *value = [aPub valueOfField:field inherit:NO];
                     // value may be nil, so check before calling rangeOfString:
                     if (nil != value) {
-                        NSRange range = [value rangeOfString:oldKey];
+                        NSRange range = [value rangeOfString:oldKey 
options:NSCaseInsensitiveSearch];
                         if (range.location != NSNotFound &&
                             (range.location == 0 || [invalidSet 
characterIsMember:[value characterAtIndex:range.location]]) &&
                             (NSMaxRange(range) == [value length] || 
[invalidSet characterIsMember:[value characterAtIndex:NSMaxRange(range)]])) {

Modified: trunk/bibdesk/BibItem.m
===================================================================
--- trunk/bibdesk/BibItem.m     2025-07-22 09:07:22 UTC (rev 29322)
+++ trunk/bibdesk/BibItem.m     2025-07-22 14:24:08 UTC (rev 29323)
@@ -1048,12 +1048,8 @@
     if ([NSString isEmptyString:key])
         return NO;
     
-    for (BibItem *pub in [owner publications]) {
-        if (pub != self && [key isCaseInsensitiveEqual:[pub 
valueOfField:BDSKCrossrefString inherit:NO]]) {
-            return YES;
-        }
-    }
-    return NO;
+    NSArray *crossreffedItems = [[owner publications] allItemsForCrossref:key];
+    return [crossreffedItems count] > 0 && ([crossreffedItems count] > 1 || 
[crossreffedItems firstObject] != self);
 }
 
 - (BDSKCrossrefError)canSetCrossref:(NSString *)aCrossref{

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



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

Reply via email to