This is Document.m in view mode; [Download] [Up]
#import <appkit/appkit.h>
#import "Document.h"
#import "TextController.h"
#define SAVE NX_ALERTDEFAULT
#define CLOSE NX_ALERTALTERNATE
#define CANCEL NX_ALERTOTHER
#define SAVE_ERROR "Can't save file"
#define OPEN_ERROR "Can't open file"
@implementation Document
// initialize a new document
- init
{
[super init];
[NXApp loadNibSection:"Document.nib"
owner:self withNames:NO];
// make the document the delegate of the window
// allows us to determine the current document
// in showSavePanel:
[window setDelegate:self];
// make the document the delegate of the text
// every time a key is pressed, the delegate
// of the text object will receive a
// textDidGetKeys: isEmpty: message
// this allows us to update the window from
// a clean state to a dirty state
[theText setDelegate:self];
return self;
}
// load a document from a file
- initDocumentFromFile:
(const char *)fullPathName
{
NXStream *stream;
// obtain a stream for an existing file
if (stream =
NXMapFile(fullPathName, NX_READONLY))
{
[self init];
// read text from stream
[theText readText:stream];
//update the window's title
[window setTitle:fullPathName];
// display the document
[self showDocument];
// free memory associated with stream
NXCloseMemory(stream, NX_FREEBUFFER);
return self;
}
else
{
[self showError:OPEN_ERROR];
return nil;
}
}
// display the document -- one improvement
// is to stagger the window rather than display
// each one on top of each other
- showDocument
{
// set the text selection to 1st char
[theText setSel:0 :0];
[window makeKeyAndOrderFront:self];
return self;
}
// write the document to file
- saveDocumentToFile:(const char *)fullPathName
{
NXStream *stream = NULL;
const char* title = [window title];
// get a stream first
if (stream =
(NXOpenMemory(NULL, 0, NX_WRITEONLY)))
{
// write text into stream
[theText writeText:stream];
// write the stream to the file
// and check for error code
if (NXSaveToFile(stream, fullPathName) != 0)
{
[self showError:SAVE_ERROR];
// free stream
NXCloseMemory(stream, NX_FREEBUFFER);
return nil;
}
else
// save succeeded: update misc info
{
// update the title of the window
[window setTitle:fullPathName];
// update window to clean state
[window setDocEdited:NO];
// free stream
NXCloseMemory(stream, NX_FREEBUFFER);
}
}
else
// Couldn't get stream
{
[self showError:SAVE_ERROR];
return nil;
}
return self;
}
// use an Alert panel to display error messages
- showError:(const char *)errorMessage
{
NXRunAlertPanel(NULL,
errorMessage, "OK", NULL, NULL);
return self;
}
// called every time a key is pressed
// if the window is marked dirty, we don't do
// anything -- if it's not dirty, we set
// it to dirty
- textDidGetKeys:sender isEmpty:(BOOL)flag
{
// if window is not dirty, then set
// it to dirty
if ([window isDocEdited] == NO)
[window setDocEdited:YES];
return self;
}
- free
{
// free the window since it's
// dynamically allocated
[window free];
// free everything allocated
// by the superclasses
return [super free];
}
// since the document object is the delegate of
// the window, the window will, before closing,
// send a windowWillClose: message to
// the document
- windowWillClose:sender
{
int result;
// display alert panel only if window
// is dirty
if ([window isDocEdited])
{
result = NXRunAlertPanel
([NXApp appName],
"Unsaved changes. Close Anyway?\n",
"Save",
"Close anyway",
"Cancel");
switch(result)
{
case SAVE:
// display savepanel;
// showSavePanel: returns
// nil if user presses Cancel
// this prevents window from
// closing
return [textController
showSavePanel:sender];
break;
case CLOSE:
// delay freeing the object until
// we are done with the current
// event (closing the window)
return [NXApp delayedFree:self];
case CANCEL:
// returning nil prevents the window
// from closing
return nil;
}
}
return self;
}
- window
{
return window;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.