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.