Revision: 29374
http://sourceforge.net/p/bibdesk/svn/29374
Author: hofman
Date: 2025-07-28 08:36:23 +0000 (Mon, 28 Jul 2025)
Log Message:
-----------
change order of method implementations
Modified Paths:
--------------
trunk/bibdesk/BibDocument.m
Modified: trunk/bibdesk/BibDocument.m
===================================================================
--- trunk/bibdesk/BibDocument.m 2025-07-26 22:45:41 UTC (rev 29373)
+++ trunk/bibdesk/BibDocument.m 2025-07-28 08:36:23 UTC (rev 29374)
@@ -994,6 +994,305 @@
}
#pragma mark -
+#pragma mark Opening and Loading Files
+
+- (BOOL)checkEncoding:(NSStringEncoding *)encodingPtr forURL:(NSURL
*)absoluteURL error:(NSError **)outError {
+ // make sure we reread the setup from extended attributes from the file,
in particular on revert
+ mainWindowSetupDictionary = nil;
+
+ NSStringEncoding encoding = *encodingPtr;
+
+ // This is only a sanity check; an encoding of 0 is not valid, so is a
signal we should ignore xattrs; could only check for public.text UTIs, but it
will be zero if it was never written (and we don't warn in that case). The
user can do many things to make the attribute incorrect, so this isn't very
robust.
+ NSStringEncoding encodingFromFile = [self
stringEncodingForSetupKey:BDSKDocumentStringEncodingKey
defaultValue:BDSKNoStringEncoding];
+
+ if (encodingFromFile == BDSKNoStringEncoding)
+ encodingFromFile = [[NSFileManager defaultManager]
appleStringEncodingAtURL:absoluteURL error:NULL] ?: BDSKNoStringEncoding;
+
+ if (encodingFromFile == BDSKNoStringEncoding || encodingFromFile ==
encoding)
+ 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];
+ *outError = error;
+ }
+
+ // If we allow the user to reopen here, NSDocumentController puts up an
open failure here when we return NO from this instance, and the message appears
after the successfully opened file is on-screen...which is confusing, to say
the least.
+ NSAlert *alert = [[NSAlert alloc] init];
+ [alert setMessageText:NSLocalizedString(@"Incorrect encoding", @"error
title when opening file")];
+ [alert setInformativeText:[NSString
stringWithFormat:NSLocalizedString(@"The document will be opened with encoding
%@, but it was previously saved with encoding %@. You should cancel opening
and then reopen with the correct encoding.", @"Informative text in alert dialog
when opening a document with different encoding"), [NSString
localizedNameOfStringEncoding:encoding], [NSString
localizedNameOfStringEncoding:encodingFromFile]]];
+ [alert addButtonWithTitle:NSLocalizedString(@"Cancel", @"Button title")];
+ [alert addButtonWithTitle:NSLocalizedString(@"Reopen", @"Button title")];
+ [alert addButtonWithTitle:NSLocalizedString(@"Ignore", @"Button title")];
+
+ NSInteger rv = [alert runModal];
+
+ if (rv == NSAlertFirstButtonReturn) {
+ // the user said to give up
+ return NO;
+ } else if (rv == NSAlertSecondButtonReturn) {
+ // we just use the encoding which was used for saving
+ *encodingPtr = encodingFromFile;
+ return YES;
+ } else {
+ NSLog(@"User ignored encoding alert");
+ return YES;
+ }
+}
+
+- (BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)aType
error:(NSError **)outError
+{
+ BOOL success = NO;
+ NSError *error = nil;
+
+ // when using the Open panel this should be initialized to the selected
encoding, otherwise the default encoding from the prefs, or for revert whatever
it was
+ NSStringEncoding encoding = [[BDSKDocumentController
sharedDocumentController] lastSelectedEncodingForURL:absoluteURL];
+ if (encoding == BDSKNoStringEncoding)
+ encoding = [self documentStringEncoding];
+ else
+ [self setDocumentStringEncoding:encoding];
+
+ if (NO == [self checkEncoding:&encoding forURL:absoluteURL error:&error]) {
+ // wrong encoding and the user said to give up
+ if (outError) *outError = error;
+ return NO;
+ }
+
+ NSData *data = [NSData dataWithContentsOfURL:absoluteURL
options:NSUncachedRead error:&error];
+ if (data == nil) {
+ if (outError) *outError = error;
+ return NO;
+ }
+
+ if ([aType isEqualToString:BDSKBibTeXDocumentType]){
+ success = [self readFromBibTeXData:data string:nil fromURL:absoluteURL
encoding:encoding error:&error];
+ }else{
+ // sniff the string to see what format we got
+ 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];
+ }else if(type == BDSKStringTypeBibTeX){
+ success = [self readFromBibTeXData:data string:string
fromURL:absoluteURL encoding:encoding error:&error];
+ }else if (type == BDSKStringTypeNoKeyBibTeX){
+ error = [NSError mutableLocalErrorWithCode:kBDSKParserFailed
localizedDescription:NSLocalizedString(@"Unable To Open Document", @"Error
description")];
+ [error setValue:NSLocalizedString(@"This file appears to contain
invalid BibTeX because of missing cite keys. Try to open using temporary cite
keys to fix this.", @"Error informative text")
forKey:NSLocalizedRecoverySuggestionErrorKey];
+ }else if (type == BDSKStringTypeUnknown){
+ error = [NSError mutableLocalErrorWithCode:kBDSKParserFailed
localizedDescription:NSLocalizedString(@"Unable To Open Document", @"Error
description")];
+ [error setValue:NSLocalizedString(@"This text file does not
contain a recognized data type.", @"Error informative text")
forKey:NSLocalizedRecoverySuggestionErrorKey];
+ }else{
+ NSArray *newPubs = [BDSKStringParser itemsFromString:string
ofType:type error:&error];
+ if (newPubs) {
+ [self setPublications:newPubs macros:nil documentInfo:nil
groups:nil frontMatter:nil encoding:[self documentStringEncoding]];
+ // since we can't save other files in their native format
(BibTeX is handled separately)
+ [self setFileURL:nil];
+ success = YES;
+ } else {
+ error = [NSError mutableLocalErrorWithCode:kBDSKParserFailed
localizedDescription:NSLocalizedString(@"Unable To Open Document", @"Error
description")];
+ [error setValue:NSLocalizedString(@"This text file does not
contain a recognized data type.", @"Error informative text")
forKey:NSLocalizedRecoverySuggestionErrorKey];
+ }
+ }
+ }
+
+ if(success == NO && outError) *outError = error;
+
+ return success;
+}
+
+- (BOOL)readFromBibTeXData:(NSData *)data string:(NSString *)string
fromURL:(NSURL *)absoluteURL encoding:(NSStringEncoding)encoding error:(NSError
**)outError {
+ NSURL *fileURL = absoluteURL;
+ NSStringEncoding parserEncoding = encoding;
+
+ if ([BDSKBibTeXParser isUnparseableEncoding:encoding]) {
+ if (string == nil)
+ string = [[NSString alloc] initWithData:data encoding:encoding];
+ if([string canBeConvertedToEncoding:NSUTF8StringEncoding]){
+ data = [string dataUsingEncoding:NSUTF8StringEncoding];
+ fileURL = [[NSFileManager defaultManager]
temporaryFileURLWithBasename:[fileURL lastPathComponent]];
+ [data writeToURL:fileURL atomically:YES];
+ parserEncoding = NSUTF8StringEncoding;
+ }else{
+ NSLog(@"Unable to convert data from encoding %@ to UTF-8",
[NSString localizedNameOfStringEncoding:encoding]);
+ }
+ }
+
+ NSError *error = nil;
+ NSArray *newPubs;
+ NSMapTable *newMacros = nil;
+ NSDictionary *newGroups = nil;
+ NSMutableDictionary *newDocumentInfo = nil;
+ NSString *newFrontMatter = nil;
+
+ newPubs = [BDSKBibTeXParser itemsFromData:data macros:&newMacros
documentInfo:&newDocumentInfo groups:&newGroups frontMatter:&newFrontMatter
filePath:[fileURL path] owner:self encoding:parserEncoding error:&error];
+
+ // do not autogenerate the cite key, unless it is empty or a placeholder
+ [newPubs makeObjectsPerformSelector:@selector(markCiteKeyEdited)];
+
+ // @@ 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];
+ // 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];
+
+ if ([self presentError:recoveryError])
+ // the user said to keep going, so if they save, they might
clobber data...
+ // if we don't return YES, NSDocumentController puts up its lame
alert saying the document could not be opened, and we get no partial data
+ error = nil;
+ else if (outError)
+ // return NSUserCancelledError so NSDocumentController won't show
another alert
+ *outError = [NSError errorWithDomain:NSCocoaErrorDomain
code:NSUserCancelledError userInfo:@{NSUnderlyingErrorKey:error}];
+ }
+
+ if (fileURL != absoluteURL)
+ [[NSFileManager defaultManager] removeItemAtURL:fileURL error:NULL];
+
+ if (error == nil) {
+ NSMapTable *newDocInfo = [[NSMapTable alloc]
initWithKeyPointerFunctions:[NSPointerFunctions
caseInsensitiveStringPointerFunctions]
valuePointerFunctions:[NSPointerFunctions strongObjectPointerFunctions]
capacity:0];
+ [newDocumentInfo enumerateKeysAndObjectsUsingBlock:^(NSString *key,
NSString *value, BOOL *stop){
+ [newDocInfo setObject:value forKey:key];
+ }];
+ [self setPublications:newPubs macros:newMacros documentInfo:newDocInfo
groups:newGroups frontMatter:newFrontMatter encoding:encoding];
+ return YES;
+ } else {
+ return NO;
+ }
+}
+
+- (BOOL)revertToContentsOfURL:(NSURL *)absoluteURL ofType:(NSString *)typeName
error:(NSError **)outError {
+ BOOL success = [super revertToContentsOfURL:absoluteURL ofType:typeName
error:outError];
+ if (success)
+ [self runScriptHookWithName:BDSKScriptHookNameRevertDocument
forPublications:nil];
+ return success;
+}
+
+- (void)setPublications:(NSArray *)newPubs macros:(NSMapTable *)newMacros
documentInfo:(NSMapTable *)newDocumentInfo groups:(NSDictionary *)newGroups
frontMatter:(NSString *)newFrontMatter encoding:(NSStringEncoding)newEncoding {
+ NSEnumerator *wcEnum = [[self windowControllers] objectEnumerator];
+ BOOL wasLoaded = nil != [wcEnum nextObject]; // initial read is before
makeWindowControllers
+
+ if (wasLoaded) {
+ NSArray *oldPubs = [publications copy];
+ NSMapTable *oldMacros = [[[self macroResolver] macroDefinitions] copy];
+ NSMutableDictionary *oldGroups = [NSMutableDictionary dictionary];
+ NSData *groupData;
+
+ if ((groupData = serializedGroupsData([[self groups] smartGroups])))
+ [oldGroups setObject:groupData forKey:[NSNumber
numberWithUnsignedInteger:BDSKSmartGroupType]];
+ if ((groupData = serializedGroupsData([[self groups] staticGroups])))
+ [oldGroups setObject:groupData forKey:[NSNumber
numberWithUnsignedInteger:BDSKStaticGroupType]];
+ if ((groupData = serializedGroupsData([[self groups] URLGroups])))
+ [oldGroups setObject:groupData forKey:[NSNumber
numberWithUnsignedInteger:BDSKURLGroupType]];
+ if ((groupData = serializedGroupsData([[self groups] scriptGroups])))
+ [oldGroups setObject:groupData forKey:[NSNumber
numberWithUnsignedInteger:BDSKScriptGroupType]];
+
+ [[[self undoManager] prepareWithInvocationTarget:self]
setPublications:oldPubs macros:oldMacros documentInfo:[documentInfo copy]
groups:oldGroups frontMatter:frontMatter encoding:[self
documentStringEncoding]];
+
+ // we need to stop the file search controller on revert, as this will
be invalid after we update our publications
+ if ([self displaysControlView:BDSKControlViewFileSearch])
+ [self setSearchString:@""];
+ [fileSearchController terminateForDocumentURL:[self fileURL]];
+ fileSearchController = nil;
+
+ // first remove all editor windows, as they will be invalid afterwards
+ NSWindowController *wc;
+ while ((wc = [wcEnum nextObject])) {
+ if ([wc respondsToSelector:@selector(discardEditing)])
+ [wc discardEditing];
+ [wc close];
+ }
+
+ // make sure we clear all groups that are saved in the file, should
only have those for revert
+ [groups removeAllUndoableGroups]; // this also removes editor windows
for external groups
+ }
+
+ [self setDocumentStringEncoding:newEncoding];
+ [self setPublications:newPubs];
+ documentInfo = [newDocumentInfo copy];
+ [[self macroResolver] setMacroDefinitions:newMacros];
+ // important that groups are loaded after publications, otherwise the
static groups won't find their publications
+ [newGroups enumerateKeysAndObjectsUsingBlock:^(NSNumber *groupType, NSData
*data, BOOL *stop){
+ [[self groups] setGroupsOfType:[groupType unsignedIntegerValue]
fromSerializedData:data];
+ }];
+ frontMatter = newFrontMatter;
+
+ if (wasLoaded) {
+ [self setSearchString:@""];
+ [self updateFilteringGroups];
+ [self sortGroupsByKey:nil]; // resort
+ [tableView deselectAll:self]; // clear before resorting
+ [self search:nil]; // redo the search
+ [self sortPubsByKey:nil]; // resort
+ }
+}
+
+#pragma mark -
+
+- (void)setDocumentStringEncoding:(NSStringEncoding)encoding{
+ docState.documentStringEncoding = encoding;
+}
+
+- (NSStringEncoding)documentStringEncoding{
+ return docState.documentStringEncoding;
+}
+
+#pragma mark -
+
+- (void)markAsImported {
+ // set date-added for imports
+ NSDate *importDate = [NSDate date];
+ NSString *importDateDescription = [importDate standardDescription];
+ for (BibItem *pub in publications)
+ [pub markNewWithDate:importDate description:importDateDescription];
+}
+
+- (void)generateForTemporaryCiteKey:(NSString *)tmpKey {
+ NSArray *selItems = [self selectedPublications];
+ [self selectPublications:[[self publications] itemsForCiteKey:tmpKey]];
+ [self generateCiteKeysForPublications:[self selectedPublications]];
+ [self selectPublications:selItems];
+}
+
+- (void)reportTemporaryCiteKeysForNewDocument:(BOOL)isNew{
+ if([publications count] == 0)
+ return;
+
+ NSString *tmpKey = [BibItem placeholderCiteKey];
+ NSArray *tmpKeyItems = [[self publications] itemsForCiteKey:tmpKey];
+
+ if([tmpKeyItems count] == 0)
+ return;
+
+ if(isNew)
+ [self selectPublications:tmpKeyItems];
+
+ NSString *infoFormat = isNew ? NSLocalizedString(@"This document was
opened using the temporary cite key \"%@\" for the selected publications. In
order to use your file with BibTeX, you must generate valid cite keys for all
of these items. Do you want me to do this now?", @"Informative text in alert
dialog")
+ : NSLocalizedString(@"New items are added using
the temporary cite key \"%@\". In order to use your file with BibTeX, you must
generate valid cite keys for these items. Do you want me to do this now?",
@"Informative text in alert dialog");
+
+ NSAlert *alert = [[NSAlert alloc] init];
+ [alert setMessageText:NSLocalizedString(@"Temporary Cite Keys", @"Message
in alert dialog when opening a file with temporary cite keys")];
+ [alert setInformativeText:[NSString stringWithFormat:infoFormat, tmpKey]];
+ [alert addButtonWithTitle:NSLocalizedString(@"Generate", @"Button title")];
+ [alert addButtonWithTitle:NSLocalizedString(@"Don't Generate", @"Button
title")];
+ if ([documentWindow attachedSheet] == nil) {
+ [alert beginSheetModalForWindow:documentWindow
completionHandler:^(NSInteger returnCode){
+ if (returnCode == NSAlertFirstButtonReturn)
+ [self generateForTemporaryCiteKey:tmpKey];
+ }];
+ } else if ([alert runModal] == NSAlertFirstButtonReturn) {
+ [self generateForTemporaryCiteKey:tmpKey];
+ }
+}
+
+#pragma mark -
#pragma mark Document Saving
+ (NSArray *)writableTypes {
@@ -1718,305 +2017,6 @@
}
#pragma mark -
-#pragma mark Opening and Loading Files
-
-- (BOOL)checkEncoding:(NSStringEncoding *)encodingPtr forURL:(NSURL
*)absoluteURL error:(NSError **)outError {
- // make sure we reread the setup from extended attributes from the file,
in particular on revert
- mainWindowSetupDictionary = nil;
-
- NSStringEncoding encoding = *encodingPtr;
-
- // This is only a sanity check; an encoding of 0 is not valid, so is a
signal we should ignore xattrs; could only check for public.text UTIs, but it
will be zero if it was never written (and we don't warn in that case). The
user can do many things to make the attribute incorrect, so this isn't very
robust.
- NSStringEncoding encodingFromFile = [self
stringEncodingForSetupKey:BDSKDocumentStringEncodingKey
defaultValue:BDSKNoStringEncoding];
-
- if (encodingFromFile == BDSKNoStringEncoding)
- encodingFromFile = [[NSFileManager defaultManager]
appleStringEncodingAtURL:absoluteURL error:NULL] ?: BDSKNoStringEncoding;
-
- if (encodingFromFile == BDSKNoStringEncoding || encodingFromFile ==
encoding)
- 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];
- *outError = error;
- }
-
- // If we allow the user to reopen here, NSDocumentController puts up an
open failure here when we return NO from this instance, and the message appears
after the successfully opened file is on-screen...which is confusing, to say
the least.
- NSAlert *alert = [[NSAlert alloc] init];
- [alert setMessageText:NSLocalizedString(@"Incorrect encoding", @"error
title when opening file")];
- [alert setInformativeText:[NSString
stringWithFormat:NSLocalizedString(@"The document will be opened with encoding
%@, but it was previously saved with encoding %@. You should cancel opening
and then reopen with the correct encoding.", @"Informative text in alert dialog
when opening a document with different encoding"), [NSString
localizedNameOfStringEncoding:encoding], [NSString
localizedNameOfStringEncoding:encodingFromFile]]];
- [alert addButtonWithTitle:NSLocalizedString(@"Cancel", @"Button title")];
- [alert addButtonWithTitle:NSLocalizedString(@"Reopen", @"Button title")];
- [alert addButtonWithTitle:NSLocalizedString(@"Ignore", @"Button title")];
-
- NSInteger rv = [alert runModal];
-
- if (rv == NSAlertFirstButtonReturn) {
- // the user said to give up
- return NO;
- } else if (rv == NSAlertSecondButtonReturn) {
- // we just use the encoding which was used for saving
- *encodingPtr = encodingFromFile;
- return YES;
- } else {
- NSLog(@"User ignored encoding alert");
- return YES;
- }
-}
-
-- (BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)aType
error:(NSError **)outError
-{
- BOOL success = NO;
- NSError *error = nil;
-
- // when using the Open panel this should be initialized to the selected
encoding, otherwise the default encoding from the prefs, or for revert whatever
it was
- NSStringEncoding encoding = [[BDSKDocumentController
sharedDocumentController] lastSelectedEncodingForURL:absoluteURL];
- if (encoding == BDSKNoStringEncoding)
- encoding = [self documentStringEncoding];
- else
- [self setDocumentStringEncoding:encoding];
-
- if (NO == [self checkEncoding:&encoding forURL:absoluteURL error:&error]) {
- // wrong encoding and the user said to give up
- if (outError) *outError = error;
- return NO;
- }
-
- NSData *data = [NSData dataWithContentsOfURL:absoluteURL
options:NSUncachedRead error:&error];
- if (data == nil) {
- if (outError) *outError = error;
- return NO;
- }
-
- if ([aType isEqualToString:BDSKBibTeXDocumentType]){
- success = [self readFromBibTeXData:data string:nil fromURL:absoluteURL
encoding:encoding error:&error];
- }else{
- // sniff the string to see what format we got
- 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];
- }else if(type == BDSKStringTypeBibTeX){
- success = [self readFromBibTeXData:data string:string
fromURL:absoluteURL encoding:encoding error:&error];
- }else if (type == BDSKStringTypeNoKeyBibTeX){
- error = [NSError mutableLocalErrorWithCode:kBDSKParserFailed
localizedDescription:NSLocalizedString(@"Unable To Open Document", @"Error
description")];
- [error setValue:NSLocalizedString(@"This file appears to contain
invalid BibTeX because of missing cite keys. Try to open using temporary cite
keys to fix this.", @"Error informative text")
forKey:NSLocalizedRecoverySuggestionErrorKey];
- }else if (type == BDSKStringTypeUnknown){
- error = [NSError mutableLocalErrorWithCode:kBDSKParserFailed
localizedDescription:NSLocalizedString(@"Unable To Open Document", @"Error
description")];
- [error setValue:NSLocalizedString(@"This text file does not
contain a recognized data type.", @"Error informative text")
forKey:NSLocalizedRecoverySuggestionErrorKey];
- }else{
- NSArray *newPubs = [BDSKStringParser itemsFromString:string
ofType:type error:&error];
- if (newPubs) {
- [self setPublications:newPubs macros:nil documentInfo:nil
groups:nil frontMatter:nil encoding:[self documentStringEncoding]];
- // since we can't save other files in their native format
(BibTeX is handled separately)
- [self setFileURL:nil];
- success = YES;
- } else {
- error = [NSError mutableLocalErrorWithCode:kBDSKParserFailed
localizedDescription:NSLocalizedString(@"Unable To Open Document", @"Error
description")];
- [error setValue:NSLocalizedString(@"This text file does not
contain a recognized data type.", @"Error informative text")
forKey:NSLocalizedRecoverySuggestionErrorKey];
- }
- }
- }
-
- if(success == NO && outError) *outError = error;
-
- return success;
-}
-
-- (BOOL)readFromBibTeXData:(NSData *)data string:(NSString *)string
fromURL:(NSURL *)absoluteURL encoding:(NSStringEncoding)encoding error:(NSError
**)outError {
- NSURL *fileURL = absoluteURL;
- NSStringEncoding parserEncoding = encoding;
-
- if ([BDSKBibTeXParser isUnparseableEncoding:encoding]) {
- if (string == nil)
- string = [[NSString alloc] initWithData:data encoding:encoding];
- if([string canBeConvertedToEncoding:NSUTF8StringEncoding]){
- data = [string dataUsingEncoding:NSUTF8StringEncoding];
- fileURL = [[NSFileManager defaultManager]
temporaryFileURLWithBasename:[fileURL lastPathComponent]];
- [data writeToURL:fileURL atomically:YES];
- parserEncoding = NSUTF8StringEncoding;
- }else{
- NSLog(@"Unable to convert data from encoding %@ to UTF-8",
[NSString localizedNameOfStringEncoding:encoding]);
- }
- }
-
- NSError *error = nil;
- NSArray *newPubs;
- NSMapTable *newMacros = nil;
- NSDictionary *newGroups = nil;
- NSMutableDictionary *newDocumentInfo = nil;
- NSString *newFrontMatter = nil;
-
- newPubs = [BDSKBibTeXParser itemsFromData:data macros:&newMacros
documentInfo:&newDocumentInfo groups:&newGroups frontMatter:&newFrontMatter
filePath:[fileURL path] owner:self encoding:parserEncoding error:&error];
-
- // do not autogenerate the cite key, unless it is empty or a placeholder
- [newPubs makeObjectsPerformSelector:@selector(markCiteKeyEdited)];
-
- // @@ 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];
- // 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];
-
- if ([self presentError:recoveryError])
- // the user said to keep going, so if they save, they might
clobber data...
- // if we don't return YES, NSDocumentController puts up its lame
alert saying the document could not be opened, and we get no partial data
- error = nil;
- else if (outError)
- // return NSUserCancelledError so NSDocumentController won't show
another alert
- *outError = [NSError errorWithDomain:NSCocoaErrorDomain
code:NSUserCancelledError userInfo:@{NSUnderlyingErrorKey:error}];
- }
-
- if (fileURL != absoluteURL)
- [[NSFileManager defaultManager] removeItemAtURL:fileURL error:NULL];
-
- if (error == nil) {
- NSMapTable *newDocInfo = [[NSMapTable alloc]
initWithKeyPointerFunctions:[NSPointerFunctions
caseInsensitiveStringPointerFunctions]
valuePointerFunctions:[NSPointerFunctions strongObjectPointerFunctions]
capacity:0];
- [newDocumentInfo enumerateKeysAndObjectsUsingBlock:^(NSString *key,
NSString *value, BOOL *stop){
- [newDocInfo setObject:value forKey:key];
- }];
- [self setPublications:newPubs macros:newMacros documentInfo:newDocInfo
groups:newGroups frontMatter:newFrontMatter encoding:encoding];
- return YES;
- } else {
- return NO;
- }
-}
-
-- (BOOL)revertToContentsOfURL:(NSURL *)absoluteURL ofType:(NSString *)typeName
error:(NSError **)outError {
- BOOL success = [super revertToContentsOfURL:absoluteURL ofType:typeName
error:outError];
- if (success)
- [self runScriptHookWithName:BDSKScriptHookNameRevertDocument
forPublications:nil];
- return success;
-}
-
-- (void)setPublications:(NSArray *)newPubs macros:(NSMapTable *)newMacros
documentInfo:(NSMapTable *)newDocumentInfo groups:(NSDictionary *)newGroups
frontMatter:(NSString *)newFrontMatter encoding:(NSStringEncoding)newEncoding {
- NSEnumerator *wcEnum = [[self windowControllers] objectEnumerator];
- BOOL wasLoaded = nil != [wcEnum nextObject]; // initial read is before
makeWindowControllers
-
- if (wasLoaded) {
- NSArray *oldPubs = [publications copy];
- NSMapTable *oldMacros = [[[self macroResolver] macroDefinitions] copy];
- NSMutableDictionary *oldGroups = [NSMutableDictionary dictionary];
- NSData *groupData;
-
- if ((groupData = serializedGroupsData([[self groups] smartGroups])))
- [oldGroups setObject:groupData forKey:[NSNumber
numberWithUnsignedInteger:BDSKSmartGroupType]];
- if ((groupData = serializedGroupsData([[self groups] staticGroups])))
- [oldGroups setObject:groupData forKey:[NSNumber
numberWithUnsignedInteger:BDSKStaticGroupType]];
- if ((groupData = serializedGroupsData([[self groups] URLGroups])))
- [oldGroups setObject:groupData forKey:[NSNumber
numberWithUnsignedInteger:BDSKURLGroupType]];
- if ((groupData = serializedGroupsData([[self groups] scriptGroups])))
- [oldGroups setObject:groupData forKey:[NSNumber
numberWithUnsignedInteger:BDSKScriptGroupType]];
-
- [[[self undoManager] prepareWithInvocationTarget:self]
setPublications:oldPubs macros:oldMacros documentInfo:[documentInfo copy]
groups:oldGroups frontMatter:frontMatter encoding:[self
documentStringEncoding]];
-
- // we need to stop the file search controller on revert, as this will
be invalid after we update our publications
- if ([self displaysControlView:BDSKControlViewFileSearch])
- [self setSearchString:@""];
- [fileSearchController terminateForDocumentURL:[self fileURL]];
- fileSearchController = nil;
-
- // first remove all editor windows, as they will be invalid afterwards
- NSWindowController *wc;
- while ((wc = [wcEnum nextObject])) {
- if ([wc respondsToSelector:@selector(discardEditing)])
- [wc discardEditing];
- [wc close];
- }
-
- // make sure we clear all groups that are saved in the file, should
only have those for revert
- [groups removeAllUndoableGroups]; // this also removes editor windows
for external groups
- }
-
- [self setDocumentStringEncoding:newEncoding];
- [self setPublications:newPubs];
- documentInfo = [newDocumentInfo copy];
- [[self macroResolver] setMacroDefinitions:newMacros];
- // important that groups are loaded after publications, otherwise the
static groups won't find their publications
- [newGroups enumerateKeysAndObjectsUsingBlock:^(NSNumber *groupType, NSData
*data, BOOL *stop){
- [[self groups] setGroupsOfType:[groupType unsignedIntegerValue]
fromSerializedData:data];
- }];
- frontMatter = newFrontMatter;
-
- if (wasLoaded) {
- [self setSearchString:@""];
- [self updateFilteringGroups];
- [self sortGroupsByKey:nil]; // resort
- [tableView deselectAll:self]; // clear before resorting
- [self search:nil]; // redo the search
- [self sortPubsByKey:nil]; // resort
- }
-}
-
-#pragma mark -
-
-- (void)setDocumentStringEncoding:(NSStringEncoding)encoding{
- docState.documentStringEncoding = encoding;
-}
-
-- (NSStringEncoding)documentStringEncoding{
- return docState.documentStringEncoding;
-}
-
-#pragma mark -
-
-- (void)markAsImported {
- // set date-added for imports
- NSDate *importDate = [NSDate date];
- NSString *importDateDescription = [importDate standardDescription];
- for (BibItem *pub in publications)
- [pub markNewWithDate:importDate description:importDateDescription];
-}
-
-- (void)generateForTemporaryCiteKey:(NSString *)tmpKey {
- NSArray *selItems = [self selectedPublications];
- [self selectPublications:[[self publications] itemsForCiteKey:tmpKey]];
- [self generateCiteKeysForPublications:[self selectedPublications]];
- [self selectPublications:selItems];
-}
-
-- (void)reportTemporaryCiteKeysForNewDocument:(BOOL)isNew{
- if([publications count] == 0)
- return;
-
- NSString *tmpKey = [BibItem placeholderCiteKey];
- NSArray *tmpKeyItems = [[self publications] itemsForCiteKey:tmpKey];
-
- if([tmpKeyItems count] == 0)
- return;
-
- if(isNew)
- [self selectPublications:tmpKeyItems];
-
- NSString *infoFormat = isNew ? NSLocalizedString(@"This document was
opened using the temporary cite key \"%@\" for the selected publications. In
order to use your file with BibTeX, you must generate valid cite keys for all
of these items. Do you want me to do this now?", @"Informative text in alert
dialog")
- : NSLocalizedString(@"New items are added using
the temporary cite key \"%@\". In order to use your file with BibTeX, you must
generate valid cite keys for these items. Do you want me to do this now?",
@"Informative text in alert dialog");
-
- NSAlert *alert = [[NSAlert alloc] init];
- [alert setMessageText:NSLocalizedString(@"Temporary Cite Keys", @"Message
in alert dialog when opening a file with temporary cite keys")];
- [alert setInformativeText:[NSString stringWithFormat:infoFormat, tmpKey]];
- [alert addButtonWithTitle:NSLocalizedString(@"Generate", @"Button title")];
- [alert addButtonWithTitle:NSLocalizedString(@"Don't Generate", @"Button
title")];
- if ([documentWindow attachedSheet] == nil) {
- [alert beginSheetModalForWindow:documentWindow
completionHandler:^(NSInteger returnCode){
- if (returnCode == NSAlertFirstButtonReturn)
- [self generateForTemporaryCiteKey:tmpKey];
- }];
- } else if ([alert runModal] == NSAlertFirstButtonReturn) {
- [self generateForTemporaryCiteKey:tmpKey];
- }
-}
-
-#pragma mark -
#pragma mark String representations
- (NSString *)bibTeXStringDroppingInternal:(BOOL)drop forPublications:(NSArray
*)items{
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