This is IArticleD.m in view mode; [Download] [Up]
#import "IArticleD.h" #import <c.h> #import <libc.h> #import <sys/types.h> #import <sys/stat.h> #import <sys/dir.h> #import <ctype.h> #import <streams/streams.h> #import <appkit/Panel.h> #import "data_types.h" #import "InfoD.h" #import "ITextD.h" #import "IAppDelegate.h" #import "IMediaD.h" #import "IBinaryD.h" #import "IMMEditor.h" #import "IMediaTable.h" #import "IExternalTable.h" #import "ILocalFileD.h" #import "INewsD.h" #import "Localization.h" #import "errdebug.h" // IArticleD is the article object. It must support some but not all of the // methods of the media class. Basically, the article object contains the // data for the article. An IMMEditor object is needed to view/edit the // object. @implementation IArticleD static NXAtom fileExtension; static IMMEditor *theEditor; + initialize { fileExtension = NXUniqueStringNoCopy(MM_FILE_EXTENSION); return(self); } + (NXAtom)fileExtension { return(fileExtension); } + (NXAtom)pasteboardType { return(NULL); } + editorWillBeFreed:anEditor { if (anEditor = theEditor) { theEditor = nil; } return(self); } - init { [super initWithKey:""]; externals = [List allocFromZone:[self zone]]; objects = [List allocFromZone:[self zone]]; return(self); } - initWithKey:(const char *)aKey { [super initWithKey:aKey]; externals = [List allocFromZone:[self zone]]; // list of external objects objects = [List allocFromZone:[self zone]]; // list of media objects return(self); } - openEditor { if (editor == nil) { [self editor]; } [[editor window] makeKeyAndOrderFront:self]; return(editor); } // editor will create a new editor or reuse an existing editor for this article // if one does not already exists. - editor { const char *multipleEditors; if (editor == nil) { [external incrementReferenceCount]; if ((multipleEditors = NXGetDefaultValue(OWNER, MULTIPLEVIEWERFLAG)) != 0 && multipleEditors[0] == 'N' && theEditor != nil && [theEditor detachArticle] != nil) { // reuse the existing editor editor = theEditor; } else { LoadLocalNib("MMRTFEditor.nib",self,NO,NULL); // MMRTFEditor.nib should be located in default zone // [NXApp loadNibSection:"MMRTFEditor.nib" owner:self withNames:NO // fromZone:NXCreateZone(vm_page_size, vm_page_size, YES)]; [editor setSizeAndPosition]; theEditor = editor; } [[editor window] makeKeyAndOrderFront:self]; [editor displayArticle:self]; } [[editor window] makeKeyAndOrderFront:self]; [[editor window] makeFirstResponder:[editor text]]; [[NXApp delegate] editorDidBecomeKey:self]; [[NXApp delegate] setPreviousContext:[NXApp activateSelf:YES]]; return(editor); } - setEditor:theEditor { editor = theEditor; return(self); } - editorWillClose:sender { editor = nil; if ([external decrementReferenceCount] == 0) { [external free]; } return(self); } - setExternal:(IExternalD *)theExternal { external = theExternal; return(self); } - external { return(external); } // Recursive save is neccessary for hypermedia documents. It should handle // both trees and graphs. The only real difficulty is that, a referenced // article must have its domain and key set before the article doing the // referencing is saved. - recursiveSaveToDomain:(NXAtom)domain { int i; id externalObject; id object; BOOL flag; IArticleD *article; NXAtom fetchDomain; const char *fetchPath; article = [[self editor] sendArticle]; // Very important that the proper domain be set before accessing key. // Although the representation has not not been written to the external // we must set the domain and path and clear dirty flag here otherwise // for graphs with loops this routine would do an infinite recursion. // Hence this is needed for recursive post of graphs with loops. Setting // the domain and path may be interpreted as a save is scheduled for // that domain and path. if ([(id)[IExternalTable externalModuleForDomain:domain] setSaveDomainAndPath:article] == nil) { return(nil); } for (i = 0; (externalObject = [externals objectAt:i]) != nil; ++i) { fetchDomain = [externalObject currentDomain]; fetchPath = [externalObject currentPath]; // check if already exists on NNTP server and post if not if ([externalObject keyForDomain:domain isDirty:&flag] == NULL || flag == YES) { // special handling for articles that are fetched from NNTP server // neccessary since they are fetched asychronously if ((object = [externalObject objectExists]) != nil || (fetchDomain != [INewsD domain] && (object = [externalObject object]) != nil)) { // external object really exists so do recursion if ([object recursiveSaveToDomain:domain] == nil) { // cancelling in the middle results in a partial // recursive save i.e., no clean up is done return(nil); } } else { // since articles are fetched asynchronously from NNTP // server object will be nill in this case NXRunAlertPanel(LoStr(MMEDITOR), LoStr("%s.%s does not exists locally and will not be " "saved."), NULL, NULL, NULL, fetchPath, fetchDomain); } } } // At this point all referenced articles have already been saved so // they have valid keys in the domain if ([(id)[IExternalTable externalModuleForDomain:domain] saveWithoutPrompt:[editor sendArticle]] == YES) { return(self); } else { return(nil); } } // referenceAllObjects/unreferenceAllObjects is neccessary to create // temporary references to objects in the article since the real references // are created too late in some unforseen cases and the objects will be // deleted. - referenceAllObjects { int i; id object; for (i = 0; (object = [self objectAt:i]) != nil; ++i) { if ([object respondsTo:@selector(incrementReferenceCount)] == YES) { [object incrementReferenceCount]; } } return(self); } - unreferenceAllObjects { int i; id object; for (i = 0; (object = [self objectAt:i]) != nil; ++i) { if ([object respondsTo:@selector(incrementReferenceCount)] == YES) { [object decrementReferenceCount]; } } return(self); } - setObjectCount:(int)count { objectCount = count; return(self); } - (int)objectCount { return(objectCount); } - (List *)externalsList { return(externals); } - (List *)objectsList { return(objects); } - free { [externals freeObjects]; [externals free]; [objects free]; return([super free]); } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.