Revision: 30095
          http://sourceforge.net/p/bibdesk/svn/30095
Author:   hofman
Date:     2026-03-01 23:00:52 +0000 (Sun, 01 Mar 2026)
Log Message:
-----------
replace mutale error class by building mutable userInfo dictionary

Modified Paths:
--------------
    trunk/bibdesk/BDSKEditor.m
    trunk/bibdesk/BDSKScriptGroup.m
    trunk/bibdesk/BDSKStringParser.m
    trunk/bibdesk/BDSKURLGroup.m
    trunk/bibdesk/BDSKWebParser.m
    trunk/bibdesk/BibDocument.m
    trunk/bibdesk/BibItem.m
    trunk/bibdesk/NSData_BDSKExtensions.m
    trunk/bibdesk/NSError_BDSKExtensions.h
    trunk/bibdesk/NSError_BDSKExtensions.m

Modified: trunk/bibdesk/BDSKEditor.m
===================================================================
--- trunk/bibdesk/BDSKEditor.m  2026-03-01 22:04:24 UTC (rev 30094)
+++ trunk/bibdesk/BDSKEditor.m  2026-03-01 23:00:52 UTC (rev 30095)
@@ -2080,14 +2080,16 @@
                 if (error) {
                     BOOL allowRecovery = editorFlags.rejectFragileCharacters 
== NO && BDSKNoCrossrefError == [publication canSetCiteKey:[obj 
stringByReplacingCharactersInSet:invalidSet withString:@""]];
                     
-                    NSError *err = [NSError 
mutableLocalErrorWithCode:kBDSKFailedToCommit 
localizedDescription:NSLocalizedString(@"Invalid Value", @"Message in alert 
dialog when entering an invalid value")];
+                    NSMutableDictionary *userInfo = [NSMutableDictionary 
dictionary];
+                    [userInfo setValue:NSLocalizedString(@"Invalid Value", 
@"Message in alert dialog when entering an invalid value") 
forKey:NSLocalizedDescriptionKey];
                     if (allowRecovery) {
-                        [err setValue:NSLocalizedString(@"The cite key you 
entered contains characters that could be invalid in TeX. Do you want to keep 
them or remove them?", @"Informative text in alert dialog") 
forKey:NSLocalizedRecoverySuggestionErrorKey];
-                        [err setValue:self forKey:NSRecoveryAttempterErrorKey];
-                        [err setValue:@[NSLocalizedString(@"Remove", @"Button 
title"), NSLocalizedString(@"Keep", @"Button title")] 
forKey:NSLocalizedRecoveryOptionsErrorKey];
+                        [userInfo setValue:NSLocalizedString(@"The cite key 
you entered contains characters that could be invalid in TeX. Do you want to 
keep them or remove them?", @"Informative text in alert dialog") 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+                        [userInfo setValue:self 
forKey:NSRecoveryAttempterErrorKey];
+                        [userInfo setValue:@[NSLocalizedString(@"Remove", 
@"Button title"), NSLocalizedString(@"Keep", @"Button title")] 
forKey:NSLocalizedRecoveryOptionsErrorKey];
                     } else {
-                        [err setValue:NSLocalizedString(@"The cite key you 
entered contains characters that could be invalid in TeX.", @"Informative text 
in alert dialog") forKey:NSLocalizedRecoverySuggestionErrorKey];
+                        [userInfo setValue:NSLocalizedString(@"The cite key 
you entered contains characters that could be invalid in TeX.", @"Informative 
text in alert dialog") forKey:NSLocalizedRecoverySuggestionErrorKey];
                     }
+                    NSError *err = [NSError 
localErrorWithCode:kBDSKFailedToCommit userInfo:userInfo];
                     *error = err;
                 }
                 

Modified: trunk/bibdesk/BDSKScriptGroup.m
===================================================================
--- trunk/bibdesk/BDSKScriptGroup.m     2026-03-01 22:04:24 UTC (rev 30094)
+++ trunk/bibdesk/BDSKScriptGroup.m     2026-03-01 23:00:52 UTC (rev 30095)
@@ -233,12 +233,13 @@
     failedDownload = NO;
     
     if([[NSFileManager defaultManager] fileExistsAtPath:standardizedPath 
isDirectory:&isDir] == NO || isDir){
-        NSError *error = [NSError mutableLocalErrorWithCode:kBDSKFileNotFound 
localizedDescription:nil];
+        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
         if (isDir)
-            [error setValue:NSLocalizedString(@"Script path points to a 
directory instead of a file", @"Error description") 
forKey:NSLocalizedDescriptionKey];
+            [userInfo setValue:NSLocalizedString(@"Script path points to a 
directory instead of a file", @"Error description") 
forKey:NSLocalizedDescriptionKey];
         else
-            [error setValue:NSLocalizedString(@"The script path points to a 
file that does not exist", @"Error description") 
forKey:NSLocalizedDescriptionKey];
-        [error setValue:standardizedPath forKey:NSFilePathErrorKey];
+            [userInfo setValue:NSLocalizedString(@"The script path points to a 
file that does not exist", @"Error description") 
forKey:NSLocalizedDescriptionKey];
+        [userInfo setValue:standardizedPath forKey:NSFilePathErrorKey];
+        NSError *error = [NSError localErrorWithCode:kBDSKFileNotFound 
userInfo:userInfo];
         [self scriptDidFailWithError:error];
         // redraw and stop spinner
         [self notifyUpdate];
@@ -412,8 +413,10 @@
 
 - (void)applecriptDidFinishWithResult:(NSAppleEventDescriptor *)resultDesc 
error:(NSError *)error {
     if (error) {
-        NSError *theError = [NSError 
mutableLocalErrorWithCode:kBDSKAppleScriptError 
localizedDescription:NSLocalizedString(@"Error executing AppleScript", @"Error 
description")];
-        [theError setValue:[error localizedRecoverySuggestion] ?: [error 
localizedDescription] forKey:NSLocalizedRecoverySuggestionErrorKey];
+        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+        [userInfo setValue:NSLocalizedString(@"Error executing AppleScript", 
@"Error description") forKey:NSLocalizedDescriptionKey];
+        [userInfo setValue:[error localizedRecoverySuggestion] ?: [error 
localizedDescription] forKey:NSLocalizedRecoverySuggestionErrorKey];
+        NSError *theError = [NSError localErrorWithCode:kBDSKAppleScriptError 
userInfo:userInfo];
         [self scriptDidFailWithError:theError];
     } else {
         NSString *result = [resultDesc stringValue];
@@ -434,8 +437,10 @@
     NSUserAppleScriptTask *script = [[NSUserAppleScriptTask alloc] 
initWithURL:[NSURL fileURLWithPath:[scriptPath stringByStandardizingPath] 
isDirectory:NO] error:&initError];
     
     if (initError) {
-        NSError *theError = [NSError 
mutableLocalErrorWithCode:kBDSKAppleScriptError 
localizedDescription:NSLocalizedString(@"Unable to load AppleScript", @"Error 
description")];
-        [theError setValue:[initError localizedRecoverySuggestion] ?: 
[initError localizedDescription] forKey:NSLocalizedRecoverySuggestionErrorKey];
+        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+        [userInfo setValue:NSLocalizedString(@"Unable to load AppleScript", 
@"Error description") forKey:NSLocalizedDescriptionKey];
+        [userInfo setValue:[initError localizedRecoverySuggestion] ?: 
[initError localizedDescription] forKey:NSLocalizedRecoverySuggestionErrorKey];
+        NSError *theError = [NSError localErrorWithCode:kBDSKAppleScriptError 
userInfo:userInfo];
         [self scriptDidFailWithError:theError];
     } else {
         if (argsArray == nil)
@@ -452,8 +457,10 @@
                     NSError *initError2 = nil;
                     NSUserAppleScriptTask *script2 = [[NSUserAppleScriptTask 
alloc] initWithURL:[NSURL fileURLWithPath:[scriptPath 
stringByStandardizingPath] isDirectory:NO] error:&initError2];
                     if (initError2) {
-                        NSError *theError = [NSError 
mutableLocalErrorWithCode:kBDSKAppleScriptError 
localizedDescription:NSLocalizedString(@"Unable to load AppleScript", @"Error 
description")];
-                        [theError setValue:[initError2 
localizedRecoverySuggestion] ?: [initError2 localizedDescription] 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+                        NSMutableDictionary *userInfo = [NSMutableDictionary 
dictionary];
+                        [userInfo setValue:NSLocalizedString(@"Unable to load 
AppleScript", @"Error description") forKey:NSLocalizedDescriptionKey];
+                        [userInfo setValue:[initError2 
localizedRecoverySuggestion] ?: [initError2 localizedDescription] 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+                        NSError *theError = [NSError 
localErrorWithCode:kBDSKAppleScriptError userInfo:userInfo];
                         [self scriptDidFailWithError:theError];
                     } else {
                         [script2 executeWithAppleEvent:nil 
completionHandler:^(NSAppleEventDescriptor *result2, NSError *error2){

Modified: trunk/bibdesk/BDSKStringParser.m
===================================================================
--- trunk/bibdesk/BDSKStringParser.m    2026-03-01 22:04:24 UTC (rev 30094)
+++ trunk/bibdesk/BDSKStringParser.m    2026-03-01 23:00:52 UTC (rev 30095)
@@ -120,11 +120,13 @@
     }
     
     if([parseError isLocalErrorWithCode:kBDSKBibTeXParserFailed]){
-        NSError *error = [NSError 
mutableLocalErrorWithCode:kBDSKBibTeXParserFailed 
localizedDescription:NSLocalizedString(@"Error Reading String", @"Message in 
alert dialog when failing to parse dropped or copied string")];
-        [error setValue:NSLocalizedString(@"There was a problem inserting the 
data. Do you want to ignore this data, open a window containing the data to 
edit it and remove the errors, or keep going and use everything that BibDesk 
could parse?\n(It's likely that choosing \"Keep Going\" will lose some data.)", 
@"Informative text in alert dialog") 
forKey:NSLocalizedRecoverySuggestionErrorKey];
-        [error setValue:[BDSKErrorObjectController 
sharedErrorObjectController] forKey:NSRecoveryAttempterErrorKey];
-        [error setValue:@[NSLocalizedString(@"Cancel", @"Button title"), 
NSLocalizedString(@"Keep going", @"Button title"), NSLocalizedString(@"Edit 
data", @"Button title")] forKey:NSLocalizedRecoveryOptionsErrorKey];
-        [error setValue:parseError forKey:NSUnderlyingErrorKey];
+        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+        [userInfo setValue:NSLocalizedString(@"Error Reading String", 
@"Message in alert dialog when failing to parse dropped or copied string") 
forKey:NSLocalizedDescriptionKey];
+        [userInfo setValue:NSLocalizedString(@"There was a problem inserting 
the data. Do you want to ignore this data, open a window containing the data to 
edit it and remove the errors, or keep going and use everything that BibDesk 
could parse?\n(It's likely that choosing \"Keep Going\" will lose some data.)", 
@"Informative text in alert dialog") 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+        [userInfo setValue:[BDSKErrorObjectController 
sharedErrorObjectController] forKey:NSRecoveryAttempterErrorKey];
+        [userInfo setValue:@[NSLocalizedString(@"Cancel", @"Button title"), 
NSLocalizedString(@"Keep going", @"Button title"), NSLocalizedString(@"Edit 
data", @"Button title")] forKey:NSLocalizedRecoveryOptionsErrorKey];
+        [userInfo setValue:parseError forKey:NSUnderlyingErrorKey];
+        NSError *error = [NSError localErrorWithCode:kBDSKBibTeXParserFailed 
userInfo:userInfo];
         parseError = error;
     }
     

Modified: trunk/bibdesk/BDSKURLGroup.m
===================================================================
--- trunk/bibdesk/BDSKURLGroup.m        2026-03-01 22:04:24 UTC (rev 30094)
+++ trunk/bibdesk/BDSKURLGroup.m        2026-03-01 23:00:52 UTC (rev 30095)
@@ -175,12 +175,13 @@
             }
             [self getPublications];
         } else {
-            NSError *error = [NSError 
mutableLocalErrorWithCode:kBDSKFileNotFound localizedDescription:nil];
+            NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
             if (isDir)
-                [error setValue:NSLocalizedString(@"URL points to a directory 
instead of a file", @"Error description") forKey:NSLocalizedDescriptionKey];
+                [userInfo setValue:NSLocalizedString(@"URL points to a 
directory instead of a file", @"Error description") 
forKey:NSLocalizedDescriptionKey];
             else
-                [error setValue:NSLocalizedString(@"The URL points to a file 
that does not exist", @"Error description") forKey:NSLocalizedDescriptionKey];
-            [error setValue:[theURL path] forKey:NSFilePathErrorKey];
+                [userInfo setValue:NSLocalizedString(@"The URL points to a 
file that does not exist", @"Error description") 
forKey:NSLocalizedDescriptionKey];
+            [userInfo setValue:[theURL path] forKey:NSFilePathErrorKey];
+            NSError *error = [NSError localErrorWithCode:kBDSKFileNotFound 
userInfo:userInfo];
             [download cancel];
             [self download:download didCompleteWithError:error];
         }

Modified: trunk/bibdesk/BDSKWebParser.m
===================================================================
--- trunk/bibdesk/BDSKWebParser.m       2026-03-01 22:04:24 UTC (rev 30094)
+++ trunk/bibdesk/BDSKWebParser.m       2026-03-01 23:00:52 UTC (rev 30095)
@@ -195,9 +195,11 @@
         
         // set default error when no error was returned
         if (success == NO && error == nil) {
-            error = [NSError mutableLocalErrorWithCode:kBDSKWebParserFailed 
localizedDescription:NSLocalizedString(@"No search results found", @"Web parser 
error")];
-            [error setValue:NSLocalizedString(@"Unable to parse this page.  
Please report this to BibDesk's developers and provide the URL.", @"Web parser 
error") forKey:NSLocalizedRecoverySuggestionErrorKey];
-            [error setValue:[self URL] forKey:NSURLErrorKey];
+            NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+            [userInfo setValue:NSLocalizedString(@"No search results found", 
@"Web parser error") forKey:NSLocalizedDescriptionKey];
+            [userInfo setValue:NSLocalizedString(@"Unable to parse this page.  
Please report this to BibDesk's developers and provide the URL.", @"Web parser 
error") forKey:NSLocalizedRecoverySuggestionErrorKey];
+            [userInfo setValue:[self URL] forKey:NSURLErrorKey];
+            error = [NSError localErrorWithCode:kBDSKWebParserFailed 
userInfo:userInfo];
         }
         
         [[self delegate] webParser:self didFinishWithSuccess:success 
error:error];

Modified: trunk/bibdesk/BibDocument.m
===================================================================
--- trunk/bibdesk/BibDocument.m 2026-03-01 22:04:24 UTC (rev 30094)
+++ trunk/bibdesk/BibDocument.m 2026-03-01 23:00:52 UTC (rev 30095)
@@ -1015,10 +1015,12 @@
         return YES;
     
     if (outError) {
-        NSError *error = [NSError 
mutableLocalErrorWithCode:kBDSKStringEncodingError 
localizedDescription:NSLocalizedString(@"Incorrect encoding", @"Message in 
alert dialog when opening a document with different encoding")];
-        [error setValue:[NSString stringWithFormat:NSLocalizedString(@"BibDesk 
tried to open the document using encoding %@, but it should have been opened 
with encoding %@.", @"Informative text in alert dialog when opening a document 
with different encoding"), [NSString localizedNameOfStringEncoding:encoding], 
[NSString localizedNameOfStringEncoding:encodingFromFile]] 
forKey:NSLocalizedRecoverySuggestionErrorKey];
-        [error setValue:absoluteURL forKey:NSURLErrorKey];
-        [error setValue:[NSNumber numberWithUnsignedInteger:encoding] 
forKey:NSStringEncodingErrorKey];
+        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+        [userInfo setValue:NSLocalizedString(@"Incorrect encoding", @"Message 
in alert dialog when opening a document with different encoding") 
forKey:NSLocalizedDescriptionKey];
+        [userInfo setValue:[NSString 
stringWithFormat:NSLocalizedString(@"BibDesk tried to open the document using 
encoding %@, but it should have been opened with encoding %@.", @"Informative 
text in alert dialog when opening a document with different encoding"), 
[NSString localizedNameOfStringEncoding:encoding], [NSString 
localizedNameOfStringEncoding:encodingFromFile]] 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+        [userInfo setValue:absoluteURL forKey:NSURLErrorKey];
+        [userInfo setValue:[NSNumber numberWithUnsignedInteger:encoding] 
forKey:NSStringEncodingErrorKey];
+        NSError *error = [NSError localErrorWithCode:kBDSKStringEncodingError 
userInfo:userInfo];
         *outError = error;
     }
     
@@ -1076,9 +1078,11 @@
         NSString *string = [[NSString alloc] initWithData:data 
encoding:encoding];
         BDSKStringType type = [string contentStringType];
         if(string == nil){
-            error = [NSError mutableLocalErrorWithCode:kBDSKParserFailed 
localizedDescription:NSLocalizedString(@"Unable To Open Document", @"Error 
description")];
-            [error setValue:[NSString 
stringWithFormat:NSLocalizedString(@"Unable to interpret data as %@.  Try a 
different encoding.", @"Error informative text"), [NSString 
localizedNameOfStringEncoding:encoding]] 
forKey:NSLocalizedRecoverySuggestionErrorKey];
-            [error setValue:[NSNumber numberWithUnsignedInteger:encoding] 
forKey:NSStringEncodingErrorKey];
+            NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+            [userInfo setValue:NSLocalizedString(@"Unable To Open Document", 
@"Error description") forKey:NSLocalizedDescriptionKey];
+            [userInfo setValue:[NSString 
stringWithFormat:NSLocalizedString(@"Unable to interpret data as %@.  Try a 
different encoding.", @"Error informative text"), [NSString 
localizedNameOfStringEncoding:encoding]] 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+            [userInfo setValue:[NSNumber numberWithUnsignedInteger:encoding] 
forKey:NSStringEncodingErrorKey];
+            error = [NSError localErrorWithCode:kBDSKParserFailed 
userInfo:userInfo];
         }else if(type == BDSKStringTypeBibTeX){
             success = [self readFromBibTeXData:data string:string 
fromURL:absoluteURL encoding:encoding error:&error];
         }else if (type == BDSKStringTypeNoKeyBibTeX){
@@ -1135,14 +1139,16 @@
     // @@ move this to NSDocumentController; need to figure out where to add 
it, though
     // @@ should we check for kBDSKBibTeXParserFailed instead? The difference 
is whether we ignore warnings for circular macros 
(kBDSKParserIgnoredFrontMatter), which we used to do
     if (error) {
-        NSError *recoveryError = [NSError mutableLocalErrorWithCode:[error 
code] localizedDescription:[error localizedDescription] ?: 
NSLocalizedString(@"Error reading file!", @"Message in alert dialog when unable 
to read file")];
-        [recoveryError setValue:NSLocalizedString(@"There was a problem 
reading the file.  Do you want to give up, edit the file to correct the errors, 
or keep going with everything that could be analyzed?\n\nIf you choose \"Keep 
Going\" and then save the file, you will probably lose data.", @"Informative 
text in alert dialog") forKey:NSLocalizedRecoverySuggestionErrorKey];
-        [recoveryError setValue:[BDSKErrorObjectController 
sharedErrorObjectController] forKey:NSRecoveryAttempterErrorKey];
-        [recoveryError setValue:@[NSLocalizedString(@"Give Up", @"Button 
title"), NSLocalizedString(@"Keep Going", @"Button title"), 
NSLocalizedString(@"Edit File", @"Button title")] 
forKey:NSLocalizedRecoveryOptionsErrorKey];
-        [recoveryError setValue:error forKey:NSUnderlyingErrorKey];
+        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+        [userInfo setValue:[error localizedDescription] ?: 
NSLocalizedString(@"Error reading file!", @"Message in alert dialog when unable 
to read file") forKey:NSLocalizedDescriptionKey];
+        [userInfo setValue:NSLocalizedString(@"There was a problem reading the 
file.  Do you want to give up, edit the file to correct the errors, or keep 
going with everything that could be analyzed?\n\nIf you choose \"Keep Going\" 
and then save the file, you will probably lose data.", @"Informative text in 
alert dialog") forKey:NSLocalizedRecoverySuggestionErrorKey];
+        [userInfo setValue:[BDSKErrorObjectController 
sharedErrorObjectController] forKey:NSRecoveryAttempterErrorKey];
+        [userInfo setValue:@[NSLocalizedString(@"Give Up", @"Button title"), 
NSLocalizedString(@"Keep Going", @"Button title"), NSLocalizedString(@"Edit 
File", @"Button title")] forKey:NSLocalizedRecoveryOptionsErrorKey];
+        [userInfo setValue:error forKey:NSUnderlyingErrorKey];
         // initial read is before makeWindowControllers, tell the 
recoveryAttempter to remove this document when accepting the error
         if ([[self windowControllers] count] == 0)
-            [recoveryError setValue:self forKey:BDSKFailedDocumentErrorKey];
+            [userInfo setValue:self forKey:BDSKFailedDocumentErrorKey];
+        NSError *recoveryError = [NSError localErrorWithCode:[error code] 
userInfo:userInfo];
         
         if ([self presentError:recoveryError])
             // the user said to keep going, so if they save, they might 
clobber data...
@@ -1467,8 +1473,11 @@
         // @@ do this in fileWrapperOfType:forPublications:error:?  should 
just use error localizedDescription
         NSString *errMsg = [nsError 
valueForKey:NSLocalizedRecoverySuggestionErrorKey] ?: NSLocalizedString(@"The 
underlying cause of this error is unknown.  Please submit a bug report with the 
file attached.", @"Error informative text");
         
-        nsError = [NSError mutableLocalErrorWithCode:kBDSKDocumentSaveError 
localizedDescription:errTitle underlyingError:nsError];
-        [nsError setValue:errMsg 
forKey:NSLocalizedRecoverySuggestionErrorKey];        
+        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+        [userInfo setValue:errTitle forKey:NSLocalizedDescriptionKey];
+        [userInfo setValue:errMsg 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+        [userInfo setValue:nsError forKey:NSUnderlyingErrorKey];
+        nsError = [NSError localErrorWithCode:kBDSKDocumentSaveError 
userInfo:userInfo];
     }
     
     // setting to nil is okay
@@ -1668,8 +1677,11 @@
                 [message appendString:NSLocalizedString(@"Please report this 
error to BibDesk's developers.", @"Error informative text")];
             }
             
-            error = [NSError mutableLocalErrorWithCode:kBDSKDocumentSaveError 
localizedDescription:NSLocalizedString(@"Unable to save document", @"Error 
description") underlyingError:error];
-            [error setValue:message 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+            NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+            [userInfo setValue:NSLocalizedString(@"Unable to save document", 
@"Error description") forKey:NSLocalizedDescriptionKey];
+            [userInfo setValue:message 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+            [userInfo setValue:error forKey:NSUnderlyingErrorKey];
+            error = [NSError localErrorWithCode:kBDSKDocumentSaveError 
userInfo:userInfo];
                         
         }
         *outError = error;
@@ -1728,8 +1740,7 @@
         
         isOK = [outputData appendDataFromString:templateFile encoding:encoding 
error:&error];
         if(NO == isOK){
-            if ([error isMutable] == NO) error = [error mutableCopy];
-            [error setValue:NSLocalizedString(@"Unable to convert template 
string.", @"string encoding error context") 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+            error = [error 
errorWithLocalizedRecoverySuggestion:NSLocalizedString(@"Unable to convert 
template string.", @"string encoding error context")];
         }
     } else if ([NSString isEmptyString:frontMatter]) {
         shouldAppendFrontMatter = NO;
@@ -1742,8 +1753,7 @@
         hasData = YES;
         isOK = [outputData appendDataFromString:frontMatter encoding:encoding 
error:&error];
         if(NO == isOK){
-            if ([error isMutable] == NO) error = [error mutableCopy];
-            [error setValue:NSLocalizedString(@"Unable to convert file 
header.", @"string encoding error context") 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+            error = [error 
errorWithLocalizedRecoverySuggestion:NSLocalizedString(@"Unable to convert file 
header.", @"string encoding error context")];
         }
         [outputData appendData:doubleNewlineData];
     }
@@ -1752,8 +1762,7 @@
         hasData = YES;
         isOK = [outputData appendDataFromString:[self documentInfoString] 
encoding:encoding error:&error];
         if(NO == isOK){
-            if ([error isMutable] == NO) error = [error mutableCopy];
-            [error setValue:NSLocalizedString(@"Unable to convert document 
info.", @"string encoding error context") 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+            error = [error 
errorWithLocalizedRecoverySuggestion:NSLocalizedString(@"Unable to convert 
document info.", @"string encoding error context")];
         }
     }
     
@@ -1764,8 +1773,7 @@
             hasData = YES;
             isOK = [outputData appendDataFromString:macroString 
encoding:encoding error:&error];
             if(NO == isOK){
-                if ([error isMutable] == NO) error = [error mutableCopy];
-                [error setValue:NSLocalizedString(@"Unable to convert 
macros.", @"string encoding error context") 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+                error = [error 
errorWithLocalizedRecoverySuggestion:NSLocalizedString(@"Unable to convert 
macros.", @"string encoding error context")];
             }
         }
     }
@@ -1794,8 +1802,7 @@
                 [outputData appendData:doubleNewlineData];
                 [outputData appendData:pubData];
             }else if([error valueForKey:NSLocalizedRecoverySuggestionErrorKey] 
== nil){
-                if ([error isMutable] == NO) error = [error mutableCopy];
-                [error setValue:[NSString 
stringWithFormat:NSLocalizedString(@"Unable to convert item with cite key %@.", 
@"string encoding error context"), [pub citeKey]] 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+                error = [error errorWithLocalizedRecoverySuggestion:[NSString 
stringWithFormat:NSLocalizedString(@"Unable to convert item with cite key %@.", 
@"string encoding error context"), [pub citeKey]]];
             }
         }
     }
@@ -1809,8 +1816,7 @@
                    [outputData appendUTF8StringData:groupData 
encoding:groupsEncoding error:&error] &&
                    [outputData appendDataFromString:@"}}" encoding:encoding 
error:&error];
             if(NO == isOK){
-                if ([error isMutable] == NO) error = [error mutableCopy];
-                [error setValue:NSLocalizedString(@"Unable to convert static 
groups.", @"string encoding error context") 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+                error = [error 
errorWithLocalizedRecoverySuggestion:NSLocalizedString(@"Unable to convert 
static groups.", @"string encoding error context")];
             }
         }
         if(isOK && (groupData = serializedGroupsData([groups smartGroups]))){
@@ -1819,8 +1825,7 @@
                    [outputData appendUTF8StringData:groupData 
encoding:groupsEncoding error:&error] &&
                    [outputData appendDataFromString:@"}}" encoding:encoding 
error:&error];
             if(NO == isOK){
-                if ([error isMutable] == NO) error = [error mutableCopy];
-                [error setValue:NSLocalizedString(@"Unable to convert smart 
groups.", @"string encoding error context") 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+                error = [error 
errorWithLocalizedRecoverySuggestion:NSLocalizedString(@"Unable to convert 
smart groups.", @"string encoding error context")];
             }
         }
         if(isOK && (groupData = serializedGroupsData([groups URLGroups]))){
@@ -1829,8 +1834,7 @@
                    [outputData appendUTF8StringData:groupData 
encoding:groupsEncoding error:&error] &&
                    [outputData appendDataFromString:@"}}" encoding:encoding 
error:&error];
             if(NO == isOK){
-                if ([error isMutable] == NO) error = [error mutableCopy];
-                [error setValue:NSLocalizedString(@"Unable to convert external 
file groups.", @"string encoding error context") 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+                error = [error 
errorWithLocalizedRecoverySuggestion:NSLocalizedString(@"Unable to convert 
external file groups.", @"string encoding error context")];
             }
         }
         if(isOK && (groupData = serializedGroupsData([groups scriptGroups]))){
@@ -1839,8 +1843,7 @@
                    [outputData appendUTF8StringData:groupData 
encoding:groupsEncoding error:&error] &&
                    [outputData appendDataFromString:@"}}" encoding:encoding 
error:&error];
             if(NO == isOK){
-                if ([error isMutable] == NO) error = [error mutableCopy];
-                [error setValue:NSLocalizedString(@"Unable to convert script 
groups.", @"string encoding error context") 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+                error = [error 
errorWithLocalizedRecoverySuggestion:NSLocalizedString(@"Unable to convert 
script groups.", @"string encoding error context")];
             }
         }
     }
@@ -1861,8 +1864,10 @@
     NSStringEncoding encoding = [self encodingForSaving];
     NSData *data = [RISString dataUsingEncoding:encoding 
allowLossyConversion:NO];
     if (nil == data && error) {
-        *error = [NSError mutableLocalErrorWithCode:kBDSKStringEncodingError 
localizedDescription:[NSString stringWithFormat:NSLocalizedString(@"Unable to 
convert the bibliography to encoding %@", @"Error description"), [NSString 
localizedNameOfStringEncoding:encoding]]];
-        [*error setValue:[NSNumber numberWithUnsignedInteger:encoding] 
forKey:NSStringEncodingErrorKey];
+        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+        [userInfo setValue:[NSString 
stringWithFormat:NSLocalizedString(@"Unable to convert the bibliography to 
encoding %@", @"Error description"), [NSString 
localizedNameOfStringEncoding:encoding]] forKey:NSLocalizedDescriptionKey];
+        [userInfo setValue:[NSNumber numberWithUnsignedInteger:encoding] 
forKey:NSStringEncodingErrorKey];
+        *error = [NSError localErrorWithCode:kBDSKStringEncodingError 
userInfo:userInfo];
     }
     return data;
 }
@@ -1872,8 +1877,10 @@
     NSStringEncoding encoding = [self encodingForSaving];
     NSData *data = [referString dataUsingEncoding:encoding 
allowLossyConversion:NO];
     if (nil == data && error) {
-        *error = [NSError mutableLocalErrorWithCode:kBDSKStringEncodingError 
localizedDescription:[NSString stringWithFormat:NSLocalizedString(@"Unable to 
convert the bibliography to encoding %@", @"Error description"), [NSString 
localizedNameOfStringEncoding:encoding]]];
-        [*error setValue:[NSNumber numberWithUnsignedInteger:encoding] 
forKey:NSStringEncodingErrorKey];
+        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+        [userInfo setValue:[NSString 
stringWithFormat:NSLocalizedString(@"Unable to convert the bibliography to 
encoding %@", @"Error description"), [NSString 
localizedNameOfStringEncoding:encoding]] forKey:NSLocalizedDescriptionKey];
+        [userInfo setValue:[NSNumber numberWithUnsignedInteger:encoding] 
forKey:NSStringEncodingErrorKey];
+        *error = [NSError localErrorWithCode:kBDSKStringEncodingError 
userInfo:userInfo];
     }
     return data;
 }
@@ -1897,9 +1904,11 @@
     NSStringEncoding encoding = [self encodingForSaving];
     NSData *data = [s dataUsingEncoding:encoding allowLossyConversion:NO];
     if (nil == data && error) {
-        *error = [NSError mutableLocalErrorWithCode:kBDSKStringEncodingError 
localizedDescription:[NSString stringWithFormat:NSLocalizedString(@"Unable to 
convert the bibliography to encoding %@", @"Error description"), [NSString 
localizedNameOfStringEncoding:encoding]]];
-        [*error setValue:[NSNumber numberWithUnsignedInteger:encoding] 
forKey:NSStringEncodingErrorKey];
-    }        
+        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+        [userInfo setValue:[NSString 
stringWithFormat:NSLocalizedString(@"Unable to convert the bibliography to 
encoding %@", @"Error description"), [NSString 
localizedNameOfStringEncoding:encoding]] forKey:NSLocalizedDescriptionKey];
+        [userInfo setValue:[NSNumber numberWithUnsignedInteger:encoding] 
forKey:NSStringEncodingErrorKey];
+        *error = [NSError localErrorWithCode:kBDSKStringEncodingError 
userInfo:userInfo];
+    }
        return data;
 }
 

Modified: trunk/bibdesk/BibItem.m
===================================================================
--- trunk/bibdesk/BibItem.m     2026-03-01 22:04:24 UTC (rev 30094)
+++ trunk/bibdesk/BibItem.m     2026-03-01 23:00:52 UTC (rev 30095)
@@ -1796,8 +1796,7 @@
     isOK = [data appendDataFromString:typeAndCiteKey encoding:encoding 
error:&error];
     
     if(isOK == NO) {
-        if ([error isMutable] == NO) error = [error mutableCopy];
-        [error setValue:[NSString stringWithFormat:NSLocalizedString(@"Unable 
to convert cite key of item with cite key \"%@\".", @"string encoding error 
context"), [self citeKey]] forKey:NSLocalizedRecoverySuggestionErrorKey];
+        error = [error errorWithLocalizedRecoverySuggestion:[NSString 
stringWithFormat:NSLocalizedString(@"Unable to convert cite key of item with 
cite key \"%@\".", @"string encoding error context"), [self citeKey]]];
     }
     
     NSData *lineSeparator = [@",\n\t" dataUsingEncoding:encoding];
@@ -1841,8 +1840,7 @@
                     isOK = [data appendDataFromString:[value 
stringAsBibTeXString] encoding:encoding error:&error];
                 
                 if(isOK == NO) {
-                    error = [error mutableCopy];
-                    [error setValue:[NSString 
stringWithFormat:NSLocalizedString(@"Unable to convert field \"%@\" of item 
with cite key \"%@\".", @"string encoding error context"), [field 
localizedFieldName], [self citeKey]] 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+                    error = [error 
errorWithLocalizedRecoverySuggestion:[NSString 
stringWithFormat:NSLocalizedString(@"Unable to convert field \"%@\" of item 
with cite key \"%@\".", @"string encoding error context"), [field 
localizedFieldName], [self citeKey]]];
                 }
             }
         }
@@ -3091,8 +3089,10 @@
     NSUInteger failureCount = [messages count];
 
     if (failureCount > 0 && outError) {
-        *outError = [NSError mutableLocalErrorWithCode:kBDSKFileNotFound 
localizedDescription:NSLocalizedString(@"Unable to migrate files completely", 
@"")];
-        [*outError setValue:messages forKey:@"messages"];
+        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+        [userInfo setValue:NSLocalizedString(@"Unable to migrate files 
completely", @"") forKey:NSLocalizedDescriptionKey];
+        [userInfo setValue:messages forKey:@"messages"];
+        *outError = [NSError localErrorWithCode:kBDSKFileNotFound 
userInfo:userInfo];
     }
     
     // Cause the file content search index (if any) to update, since we 
bypassed the normal insert mechanism where this is typically handled.  The 
date-modified will only be set if fields are removed, since the applier 
function calls setField:toValue:.

Modified: trunk/bibdesk/NSData_BDSKExtensions.m
===================================================================
--- trunk/bibdesk/NSData_BDSKExtensions.m       2026-03-01 22:04:24 UTC (rev 
30094)
+++ trunk/bibdesk/NSData_BDSKExtensions.m       2026-03-01 23:00:52 UTC (rev 
30095)
@@ -339,8 +339,10 @@
         CFIndex convertedLength = CFStringGetBytes((__bridge 
CFStringRef)string, CFRangeMake(0, length), cfEncoding, 0, FALSE, NULL, 
INT_MAX, &bufLen);
         if (convertedLength != length){
             if(error != NULL){
-                *error = [NSError 
mutableLocalErrorWithCode:kBDSKStringEncodingError 
localizedDescription:[NSString stringWithFormat:NSLocalizedString(@"Unable to 
convert string to encoding %@", @"Error description"), [NSString 
localizedNameOfStringEncoding:encoding]]];
-                [*error setValue:[NSNumber numberWithUnsignedInteger:encoding] 
forKey:NSStringEncodingErrorKey];
+                NSMutableDictionary *userInfo = [NSMutableDictionary 
dictionary];
+                [userInfo setValue:[NSString 
stringWithFormat:NSLocalizedString(@"Unable to convert string to encoding %@", 
@"Error description"), [NSString localizedNameOfStringEncoding:encoding]] 
forKey:NSLocalizedDescriptionKey];
+                [userInfo setValue:[NSNumber 
numberWithUnsignedInteger:encoding] forKey:NSStringEncodingErrorKey];
+                *error = [NSError localErrorWithCode:kBDSKStringEncodingError 
userInfo:userInfo];
             }
             return NO;
         }
@@ -354,8 +356,10 @@
     }else{
         // raise if the conversion wasn't possible, since we're not using a 
loss byte
         if(error != NULL){
-            *error = [NSError 
mutableLocalErrorWithCode:kBDSKStringEncodingError 
localizedDescription:[NSString stringWithFormat:NSLocalizedString(@"Unable to 
convert string to encoding %@", @"Error description"), [NSString 
localizedNameOfStringEncoding:encoding]]];
-            [*error setValue:[NSNumber numberWithUnsignedInteger:encoding] 
forKey:NSStringEncodingErrorKey];
+            NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+            [userInfo setValue:[NSString 
stringWithFormat:NSLocalizedString(@"Unable to convert string to encoding %@", 
@"Error description"), [NSString localizedNameOfStringEncoding:encoding]] 
forKey:NSLocalizedDescriptionKey];
+            [userInfo setValue:[NSNumber numberWithUnsignedInteger:encoding] 
forKey:NSStringEncodingErrorKey];
+            *error = [NSError localErrorWithCode:kBDSKStringEncodingError 
userInfo:userInfo];
         }
         return NO;
     }
@@ -370,8 +374,10 @@
         NSString *string = [[NSString alloc] initWithData:data 
encoding:NSUTF8StringEncoding];
         if(nil == string){
             if(error != NULL){
-                *error = [NSError 
mutableLocalErrorWithCode:kBDSKStringEncodingError 
localizedDescription:[NSString stringWithFormat:NSLocalizedString(@"Unable to 
convert data to string with encoding %@", @"Error description"), [NSString 
localizedNameOfStringEncoding:encoding]]];
-                [*error setValue:[NSNumber numberWithUnsignedInteger:encoding] 
forKey:NSStringEncodingErrorKey];
+                NSMutableDictionary *userInfo = [NSMutableDictionary 
dictionary];
+                [userInfo setValue:[NSString 
stringWithFormat:NSLocalizedString(@"Unable to convert data to string with 
encoding %@", @"Error description"), [NSString 
localizedNameOfStringEncoding:encoding]] forKey:NSLocalizedDescriptionKey];
+                [userInfo setValue:[NSNumber 
numberWithUnsignedInteger:encoding] forKey:NSStringEncodingErrorKey];
+                *error = [NSError localErrorWithCode:kBDSKStringEncodingError 
userInfo:userInfo];
             }
             return NO;
         }

Modified: trunk/bibdesk/NSError_BDSKExtensions.h
===================================================================
--- trunk/bibdesk/NSError_BDSKExtensions.h      2026-03-01 22:04:24 UTC (rev 
30094)
+++ trunk/bibdesk/NSError_BDSKExtensions.h      2026-03-01 23:00:52 UTC (rev 
30095)
@@ -72,25 +72,22 @@
 
 extern NSString * const BDSKFailedDocumentErrorKey;
 
-@interface NSError (BDSKExtensions) <NSMutableCopying>
+@interface NSError (BDSKExtensions)
 
 // returns the BibDesk-specific error domain
 @property (class, nonatomic, readonly) NSString *localErrorDomain;
 
 // returns BibDesk-specific errors that don't allow valueForKey: and 
setValue:forKey: usage
++ (instancetype)localErrorWithCode:(NSInteger)code userInfo:(NSDictionary 
*)userInfo;
 + (instancetype)localErrorWithCode:(NSInteger)code 
localizedDescription:(NSString *)description;
 + (instancetype)localErrorWithCode:(NSInteger)code 
localizedDescription:(NSString *)description underlyingError:(NSError 
*)underlyingError;
 + (instancetype)localErrorWithCode:(NSInteger)code 
localizedDescription:(NSString *)description 
localizedRecoverySuggestion:(NSString *)recoverySuggestion;
 
-// returns BibDesk-specific errors that can allow valueForKey: and 
setValue:forKey: usage
-+ (instancetype)mutableErrorWithDomain:(NSString *)domain code:(NSInteger)code 
userInfo:(nullable NSDictionary<NSString *, id> *)dict;
-+ (instancetype)mutableLocalErrorWithCode:(NSInteger)code 
localizedDescription:(nullable NSString *)description;
-+ (instancetype)mutableLocalErrorWithCode:(NSInteger)code 
localizedDescription:(nullable NSString *)description underlyingError:(NSError 
*)underlyingError;
+- (NSError *)errorWithLocalizedRecoverySuggestion:(NSString 
*)localizedRecoverySuggestion;
 
 // see if it has our local domain
 @property (nonatomic, readonly) BOOL isLocalError;
 - (BOOL)isLocalErrorWithCode:(NSInteger)code;
-@property (nonatomic, readonly) BOOL isMutable;
 
 @end
 

Modified: trunk/bibdesk/NSError_BDSKExtensions.m
===================================================================
--- trunk/bibdesk/NSError_BDSKExtensions.m      2026-03-01 22:04:24 UTC (rev 
30094)
+++ trunk/bibdesk/NSError_BDSKExtensions.m      2026-03-01 23:00:52 UTC (rev 
30095)
@@ -42,53 +42,6 @@
 
 NSString * const BDSKFailedDocumentErrorKey = @"BDSKFailedDocument";
 
-@interface BDSKMutableError : NSError
-{
-    @private
-    NSMutableDictionary *mutableUserInfo;
-}
-@end
-
-@implementation BDSKMutableError
-
-- (instancetype)initWithDomain:(NSString *)domain code:(NSInteger)code 
userInfo:(NSDictionary *)dict;
-{
-    self = [super initWithDomain:domain code:code userInfo:nil];
-    if (self) {
-        mutableUserInfo = [[NSMutableDictionary alloc] 
initWithDictionary:dict];
-    }
-    return self;
-}
-
-- (id)copyWithZone:(NSZone *)aZone
-{
-    return [[NSError alloc] initWithDomain:[self domain] code:[self code] 
userInfo:[self userInfo]];
-}
-
-- (NSDictionary *)userInfo
-{
-    return mutableUserInfo;
-}
-
-- (id)valueForUndefinedKey:(NSString *)aKey
-{
-    return [[self userInfo] valueForKey:aKey];
-}
-
-// allow setting nil values
-- (void)setValue:(id)value forUndefinedKey:(NSString *)key;
-{
-    if (value)
-        [mutableUserInfo setValue:value forKey:key];
-}
-
-- (BOOL)isMutable;
-{
-    return YES;
-}
-
-@end
-
 @implementation NSError (BDSKExtensions)
 
 + (NSString *)localErrorDomain { return BDSKErrorDomain; }
@@ -103,6 +56,11 @@
     return [self isLocalError] && [self code] == code;
 }
 
++ (instancetype)localErrorWithCode:(NSInteger)code userInfo:(NSDictionary 
*)userInfo;
+{
+    return [[self alloc] initWithDomain:[NSError localErrorDomain] code:code 
userInfo:userInfo];
+}
+
 + (instancetype)localErrorWithCode:(NSInteger)code 
localizedDescription:(NSString *)description;
 {
     NSDictionary *userInfo = @{NSLocalizedDescriptionKey: description};
@@ -121,37 +79,15 @@
     return [[self alloc] initWithDomain:[NSError localErrorDomain] code:code 
userInfo:userInfo];
 }
 
-+ (instancetype)mutableErrorWithDomain:(NSString *)domain code:(NSInteger)code 
userInfo:(NSDictionary *)dict;
+- (NSError *)errorWithLocalizedRecoverySuggestion:(NSString 
*)localizedRecoverySuggestion;
 {
-    return [[BDSKMutableError alloc] initWithDomain:domain code:code 
userInfo:dict];
+    NSMutableDictionary *userInfo = [NSMutableDictionary 
dictionaryWithDictionary:[self userInfo]];
+    [userInfo setValue:localizedRecoverySuggestion 
forKey:NSLocalizedRecoverySuggestionErrorKey];
+    return [[NSError alloc] initWithDomain:[self domain] code:[self code] 
userInfo:userInfo];
 }
 
-+ (instancetype)mutableLocalErrorWithCode:(NSInteger)code 
localizedDescription:(NSString *)description;
-{
-    NSDictionary *userInfo = description ? @{NSLocalizedDescriptionKey: 
description} : nil;
-    return [[BDSKMutableError alloc] initWithDomain:[NSError localErrorDomain] 
code:code userInfo:userInfo];
+- (id)valueForUndefinedKey:(NSString *)key {
+    return [[self userInfo] valueForKey:key];
 }
 
-+ (instancetype)mutableLocalErrorWithCode:(NSInteger)code 
localizedDescription:(NSString *)description underlyingError:(NSError 
*)underlyingError;
-{
-    NSError *error = [NSError mutableLocalErrorWithCode:code 
localizedDescription:description];
-    [error setValue:underlyingError forKey:NSUnderlyingErrorKey];
-    return error;
-}
-
-- (id)mutableCopyWithZone:(NSZone *)aZone;
-{
-    return [[BDSKMutableError alloc] initWithDomain:[self domain] code:[self 
code] userInfo:[self userInfo]];
-}
-
-- (id)valueForUndefinedKey:(NSString *)aKey
-{
-    return [[self userInfo] valueForKey:aKey];
-}
-
-- (BOOL)isMutable;
-{
-    return NO;
-}
-
 @end

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