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.