This is FileSaver.m in view mode; [Download] [Up]
// FileSaver.m // By Charles G. Fleming and Judy D. Halchin, // Educational Computing Services, Allegheny College. // Copyright 1992, 1993 Allegheny College // You may freely copy, distribute and reuse this code. // Allegheny College and the authors disclaim any warranty of any kind, // expressed or implied, as to its fitness for any particular use. // This work was partially supported by a grant from the Pew Charitable Trusts // and by an NSF Teacher Preparation Grant. #import "SaverAndRetriever.h" #import <objc/error.h> #import <appkit/SavePanel.h> #import <appkit/Application.h> #import <stdlib.h> #import <strings.h> @implementation FileSaver - (const char *)getInspectorClassName { return "FileSaverAndRetrieverInspector"; } // Initially the filename is the empty string, and the delegate and // dataDelegate are nil. - init { self = [super init]; filename = (char *)malloc(MAXPATHLEN + 1); directory = (char *)malloc(MAXPATHLEN + 1); strcpy(filename, ""); strcpy(directory, NXHomeDirectory()); return self; } - setDelegate:anObject { delegate = anObject; return self; } - setDataDelegate:anObject { dataDelegate = anObject; return self; } - setFileRetriever:anObject { fileRetriever = anObject; return self; } // Returns the file saver's delegate. - delegate { return delegate; } // Returns the file saver's dataDelegate. - dataDelegate { return dataDelegate; } // Returns the fileRetriever with which this FileSaver works - fileRetriever { return fileRetriever; } // Set the name of the file where the data will be stored. This message // can be sent by a FileRetriever object. - setFilename:(char *)name { strcpy(filename, name); return self; } // Set the path to the directory of filename. This message // can be sent by a FileRetriever object. - setDirectory:(char *)path { strcpy(directory, path); return self; } // Returns the name of the file where the data will be stored. - (char *)filename { return filename; } // Returns the directory path of the file where the data will be stored. - (char *)directory { return directory; } // If there is a file, call save, otherwise run a save panel. The save or // saveAs method will notify the delegate of any errors. - save:sender { if(strcmp(filename, "") != 0) [self save]; else [self saveAs:self]; return self; } // Run a save panel. If the cancel button is not pushed, call save. - saveAs:sender { SavePanel *savePanel = [SavePanel new]; char tempFilename[MAXPATHLEN], *lastSlash; int count; // Try to run a SavePanel. If unable to, raise an exception. if([savePanel runModalForDirectory:directory file:filename]) { // Get the filename from the save panel and split into directory // and file. strcpy(tempFilename, [savePanel filename]); lastSlash = strrchr(tempFilename, '/'); strcpy(filename, lastSlash + 1); if(lastSlash == tempFilename) { count = 1; directory[1] = '\0'; } else { count = lastSlash - tempFilename; directory[lastSlash - tempFilename] = '\0'; } strncpy(directory, tempFilename, count); [self save]; } else if([delegate respondsTo: @selector(dataWasWritten:success:errorCode:)]) [delegate dataWasWritten:self success:NO errorCode:cancelButtonPushed]; return self; } // If the information has been saved to a file, go ahead and use that file. // The dataDelegate must write the data to the stream provided. // Any errors that occur will be handled by an exception handler. // If the data has not been saved previously, call saveAs:. - (BOOL)save { NXStream *stream; char fullPathname[MAXPATHLEN]; BOOL fileSaved = NO; NX_DURING; if(strcmp(filename, "") != 0) { // Open a stream on memory. stream = NXOpenMemory(NULL, 0, NX_WRITEONLY); // Raise an exception if we were unable open a stream on memory if(!stream) NX_RAISE(noStream, self, delegate); // Raise an exception if there is no dataDelegate. if(dataDelegate == nil) NX_RAISE(noDataDelegate, self, delegate); // Send writeDataToStream: to the dataDelegate if it implements it. // if not, raise an exception. if([dataDelegate respondsTo:@selector(writeDataToStream:)]) { if (![dataDelegate writeDataToStream:stream]) NX_RAISE(dataNotWritten, self, delegate); } else NX_RAISE(doesNotRespondToMethod, self, delegate); // Construct the full pathname from the directory and file. If // the directory is "", we'll use the user's home directory. if(strcmp(directory, "") == 0) strcpy(directory, NXHomeDirectory()); // Try to save the data. If unable to, raise an exception. sprintf(fullPathname, "%s/%s", directory, filename); if(NXSaveToFile(stream, fullPathname) == -1) NX_RAISE(unableToSaveStreamToFile, self, delegate); // If all went well, tell the delegate that the data has been saved // and tell the fileRetriever the new filename. if([delegate respondsTo:@selector(dataWasWritten:success:errorCode:)]) [delegate dataWasWritten:self success:YES errorCode:noError]; if([fileRetriever respondsTo:@selector(setFilename:)]) [fileRetriever setFilename:filename]; if([fileRetriever respondsTo:@selector(setDirectory:)]) [(FileRetriever *)fileRetriever setDirectory:directory]; fileSaved = YES; } else if([delegate respondsTo: @selector(dataWasWritten:success:errorCode:)]) [delegate dataWasWritten:self success:NO errorCode:noFile]; // Here's the error handler. NX_HANDLER switch(NXLocalHandler.code) { case noStream: if([(id)NXLocalHandler.data2 respondsTo: @selector(dataWasWritten:success:errorCode:)]) [(id)NXLocalHandler.data2 dataWasWritten:(id)NXLocalHandler.data1 success:NO errorCode:noStream]; break; case noDataDelegate: if([(id)NXLocalHandler.data2 respondsTo: @selector(dataWasWritten:success:errorCode:)]) [(id)NXLocalHandler.data2 dataWasWritten:(id)NXLocalHandler.data1 success:NO errorCode:noDataDelegate]; break; case doesNotRespondToMethod: if([(id)NXLocalHandler.data2 respondsTo: @selector(dataWasWritten:success:errorCode:)]) [(id)NXLocalHandler.data2 dataWasWritten:(id)NXLocalHandler.data1 success:NO errorCode:doesNotRespondToMethod]; break; case dataNotWritten: if([(id)NXLocalHandler.data2 respondsTo: @selector(dataWasWritten:success:errorCode:)]) [(id)NXLocalHandler.data2 dataWasWritten:(id)NXLocalHandler.data1 success:NO errorCode:dataNotWritten]; break; case unableToSaveStreamToFile: if([(id)NXLocalHandler.data2 respondsTo: @selector(dataWasWritten:success:errorCode:)]) [(id)NXLocalHandler.data2 dataWasWritten:(id)NXLocalHandler.data1 success:NO errorCode:unableToSaveStreamToFile]; break; default: NX_RERAISE(); break; } NX_ENDHANDLER; //Close the stream. if(stream) NXCloseMemory(stream, NX_FREEBUFFER); return fileSaved; } - write:(NXTypedStream *)typedStream { [super write:typedStream]; NXWriteTypes(typedStream, "**", &directory, &filename); return self; } - read:(NXTypedStream *)typedStream { char *tempDirectory, *tempFilename; filename = (char *)malloc(MAXPATHLEN + 1); directory = (char *)malloc(MAXPATHLEN + 1); [super read:typedStream]; NXReadTypes(typedStream, "**", &tempDirectory, &tempFilename); strcpy(filename, tempFilename); strcpy(directory, tempDirectory); return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.