This is eTComponent.m in view mode; [Download] [Up]
///////////////////////////////////////////////////////////////////////////////
// FILENAME: eTComponent.m
// SUMMARY: Implementation of a generic external-data-container class.
// SUPERCLASS: Object
// INTERFACE: None
// PROTOCOLS: <ComponentData,
// ETFDSupport,ASCIISupport,HTMDSupport, LaTeXSupport>
// AUTHOR: Rohit Khare and Tom Zavisca
// COPYRIGHT: (c) 1994 California Institure of Technology, eText Project
///////////////////////////////////////////////////////////////////////////////
// IMPLEMENTATION COMMENTS
// This implementation is a hack: it uses system() calls to have files
// copied. This avoids setting up our own buffer functions and works
// for directories, too. This also just a default implementation; subclasses
// will most likely define their own methods.
//
// The revision of 7/19 introduces a new two-phase lifecycle,
// initInDoc:linked: followed by readComponent from path or Pboard.
//
// Eventually, there is room for an eTComponentBinder that will uniq' refs.
///////////////////////////////////////////////////////////////////////////////
// HISTORY
// 12/23/94: Patched to reset eTDoc everywhere
// 08/06/94: Added symbolic linking support.
// 07/19/94: Rewritten/Reorganized as described in Actors/eTComponent.rtf
// 07/10/94: Created.
///////////////////////////////////////////////////////////////////////////////
#import "eTComponent.h"
#define _eTComponentVERSION 20
@implementation eTComponent
// NXAtom componentName;
// NXAtom currentPath;
// BOOL shouldEdit;
// BOOL isDirty;
// BOOl isLinked;
// id etDoc;
// id icon;
//////////// ACCESSOR METHODS ////////////////
- setComponentName:(const char*)newComponentName
{componentName = NXUniqueString(newComponentName); return self;}
- (const char *) componentName
{return componentName;}
- (const char *) currentPath
{return currentPath;}
- etDoc
{return etDoc;}
- icon
{
if (!icon) {
icon = [[Application workspace] getIconForFile:currentPath];
if (!icon) icon = [NXImage findImageNamed:"NXdefaulticon"];
}
return icon;}
- (BOOL) isLinked
{return isLinked;}
- (BOOL) isMutable // this call checks shouldEdit
{return (shouldEdit && (!isLinked));}
- setShouldEdit:(BOOL) newState
{shouldEdit = newState; return self;}
- setLinked:(BOOL) newState
{isLinked = newState; return self;}
- setDoc:newDoc {
if (newDoc && [newDoc respondsTo:@selector(registerComponent:)])
etDoc = newDoc; // Always reset if possible; bugfix for shared images, 12/23
return self;
}
- touch
{isDirty=YES; return self;}
//////////// LIFECYCLE MANAGEMENT ////////////
- init // default initializer
{
return [self initInDoc:nil linked:NO];
}
- initInDoc:newDoc linked: (BOOL) linked
{
char tmp[128];
[super init];
isLinked = linked;
etDoc = newDoc;
isDirty = NO;
shouldEdit = YES;
icon = nil;
sprintf(tmp, "Untitled-%d", [NXApp uniqueID]);
componentName = NXUniqueString(tmp);
currentPath = NXUniqueString("");
return self;
}
////////////// READING/WRITING ///////////////
- readComponentFromPath:(const char*)newPath
{
char *tmp;
// Have we been passed a valid pathname?
if(!(newPath && (*newPath))) {
NXLogError("Severe Error, bad path to readComponentFromPath");
return nil;
}
if (access(newPath, F_OK|R_OK)) {
NXLogError("%s could not access(%s)", [[self class]name],newPath);
}
currentPath = NXUniqueString(newPath);
tmp = rindex(newPath,'/');
if (tmp && *(tmp+1))
componentName = NXUniqueString(tmp+1);
return self;
}
- writeComponentToPath:(NXAtom)path inFormat:(int) theFormat
{
char target[MAXPATHLEN];
char cmd[2*MAXPATHLEN];
switch(theFormat) {
case ETFD_FMT:
[etDoc registerComponent:componentName]; // always register
// if it's linked, just return.
if (isLinked) break;
sprintf(target,"%s/%s",path,componentName);
// see if the diskfile already exists
if ((!isDirty) && (!access(target, F_OK|R_OK))) break;
// ok, copy the raw bits.
if (currentPath && *currentPath && target && *target) {
sprintf(cmd,"cp -rp \"%s\" \"%s\"", currentPath, target);
system(cmd);
}
// since we have saved ETFD, reset the "clean" state
currentPath = NXUniqueString(target);
isDirty = NO;
break;
case TeXD_FMT: if (isLinked) break;
case HTMD_FMT:
// In these formats, we always force copying of the data resource
[etDoc registerComponent:componentName]; // always register
sprintf(target,"%s/%s",path,componentName);
// see if the diskfile already exists
if ((!isDirty) && (!access(target, F_OK|R_OK))) break;
if (currentPath && *currentPath && target && *target) {
sprintf(cmd,"cp -rp \"%s\" \"%s\"", currentPath, target);
system(cmd);
}
break;
}
return self;
}
- linkComponentToPath:(NXAtom)path
{
char target[MAXPATHLEN];
char cmd[2*MAXPATHLEN];
[etDoc registerComponent:componentName]; // always register
sprintf(target,"%s/%s",path,componentName);
// see if the diskfile already exists
if (access(target, F_OK|R_OK)){
if (currentPath && *currentPath && target && *target) {
sprintf(cmd,"ln -s \"%s\" \"%s\"", currentPath, target);
system(cmd);
}
}
return self;
}
- readComponentFromPboard:(Pasteboard *)thePboard
{
NXAtom foundType;
NXAtom supportedTypes[2] = {NXFilenamePboardType,
NXFileContentsPboardType};
foundType = [thePboard findAvailableTypeFrom:supportedTypes num:2];
if (foundType == NXFilenamePboardType) {
// can we derive a resource name? if not, make path the resource name
char *path;
int len;
[thePboard readType:NXFilenamePboardType data:&path length:&len];
// we only process _ONE_ filename; this defeats the tab-separation
if (index(path, '\t')) *index(path, '\t')=0;
if (rindex(path, '/')) {
componentName = NXUniqueString(rindex(path,'/')+1);
currentPath = NXUniqueString(path);
} else {
currentPath = componentName = NXUniqueString(path);
}
[thePboard deallocatePasteboardData:path length:len];
} else if (foundType == NXFileContentsPboardType) {
char *path,tmp[MAXPATHLEN];
sprintf(tmp,"/tmp/eTComponent.in.%x", [NXApp uniqueID]);
path = [thePboard readFileContentsType:NULL toFile:tmp];
currentPath = NXUniqueString(path);
componentName = NXUniqueString(rindex(path,'/')+1);
free(path); // readFile... returns a malloc'd actual path
}
return self;
}
- writeComponentToPboard:(Pasteboard *)thePboard
{
// find out where the file is and encode that to the Pboard.
if (!(*currentPath) || access(currentPath, F_OK)) return nil;
[thePboard declareTypes:&NXFilenamePboardType num:1 owner:nil];
[thePboard writeType:NXFilenamePboardType
data:currentPath length:strlen(currentPath)];
return self;
}
- addToPboard:thePboard
{
if (!(*currentPath) || access(currentPath, F_OK)) return nil;
[thePboard addTypes:&NXFilenamePboardType num:1 owner:nil];
[thePboard writeType:NXFilenamePboardType
data:currentPath length:strlen(currentPath)];
return self;
}
///////// ADDITIONAL FMT PROTOCOL SUPPORT ////////////
- readRichText:(NXStream *)stream forView:view
{
char buf[MAXPATHLEN];
const char *tmp;
int i;
id temp;
temp = [view etDoc];
if (temp && [temp respondsTo:@selector(registerComponent:)])
etDoc = temp; // Always reset if possible; bugfix for shared images, 12/23
NXScanf(stream, "%d ", &i);
if (i != _eTComponentVERSION) {
// bad version block.
NXLogError("eTComponent found unparseable version %d at position %d",
i, NXTell(stream));
return nil;
}
NXScanf(stream, "%c %c %d", &isLinked, &shouldEdit, &i); NXGetc(stream); // space-eater
isLinked -= 'A'; shouldEdit -= 'A';
if (i) NXRead(stream, buf, i);
buf[i] = 0;
currentPath = NXUniqueString(buf);
NXScanf(stream, " %d", &i); NXGetc(stream); // space-eater
if (i) NXRead(stream, buf, i);
buf[i] = 0;
componentName = NXUniqueString(buf);
if(!access(currentPath, F_OK|R_OK) || isLinked) return self;
if(etDoc && (tmp = [[etDoc docInfo] docPath])) {
sprintf(buf,"%s/%s",tmp,componentName);
if(!access(buf, F_OK|R_OK)) {
currentPath = NXUniqueString(buf);
#ifdef DEBUG
NXLogError("Found %s at %s not %s/%s", componentName,buf,currentPath,componentName);
#endif
return self;
}
}
#ifdef DEBUG
NXLogError("Could not access %s or %s! %s readRichText: failed!",
currentPath,buf,[[self class] name]);
#endif
return nil;
}
- writeRichText:(NXStream *)stream forView:view
{
// since this method is called before any writeComponents, we attempt
// to precompute the future currentPath
// RULE: if (isLinked), currentPath is valid
// RULE: otherwise, componentName is valid, so precompute currentPath
const char *tmp;
char target[MAXPATHLEN];
id temp;
temp = [view etDoc];
if (temp && [temp respondsTo:@selector(registerComponent:)])
etDoc = temp; // Always reset if possible; bugfix for shared images, 12/23
if (isLinked)
tmp = currentPath;
else {
sprintf(target, "%s/%s",[[etDoc docInfo] docPath], componentName);
tmp = target;
}
NXPrintf(stream, "%d %c %c %d %s %d %s",
_eTComponentVERSION, isLinked+'A', shouldEdit+'A',
strlen(tmp), tmp, strlen(componentName), componentName);
return self;
}
- writeASCIIRef:(NXStream *)stream forView:view
{
id temp;
temp = [view etDoc];
if (temp && [temp respondsTo:@selector(registerComponent:)])
etDoc = temp; // Always reset if possible; bugfix for shared images, 12/23
NXPrintf(stream, "A %s%s reference to the file %s\n", (isLinked ? "linked " : ""), [[self class] name], (isLinked ? currentPath : componentName));
return self;
}
- writeHTML:(NXStream *)stream forView:view
{return [self writeHTML:stream forView:view andClose:YES];}
- writeHTML:(NXStream *)stream forView:view andClose:(BOOL)closeIt
{
id temp;
temp = [view etDoc];
if (temp && [temp respondsTo:@selector(registerComponent:)])
etDoc = temp; // Always reset if possible; bugfix for shared images, 12/23
//NXPrintf(stream, "<A HREF=\"%V%V\">%v:%v</A>",
// (isLinked ? "http://localhost/" : ""),
// (isLinked ? currentPath : componentName),
// [[self class] name],(isLinked ? currentPath : componentName));
// In the NEW scheme of things, HTML component data is _ALWAYS_
// written out explicitly, so none of this localhost shit.
NXPrintf(stream,"<A HREF=\"%V\">",componentName);
if (closeIt)
NXPrintf(stream,"%v</A>",componentName);
return self;
}
- writeLaTeX:(NXStream *)stream forView:view
{return [self writeLaTeX:stream forView:view andClose:YES];}
- writeLaTeX:(NXStream *)stream forView:view andClose:(BOOL)closeIt
{
id temp;
temp = [view etDoc];
if (temp && [temp respondsTo:@selector(registerComponent:)])
etDoc = temp; // Always reset if possible; bugfix for shared images, 12/23
NXPrintf(stream, "\n\\footnote{A %w%w reference to the file %w.", (isLinked ? "linked " : ""), [[self class] name], (isLinked ? currentPath : componentName));
if (closeIt)
NXPrintf(stream, "}\n");
return self;
}
@endThese are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.