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.