This is eTRTFDFileLink.m in view mode; [Download] [Up]
///////////////////////////////////////////////////////////////////////////////
// FILENAME: eTRTFDFileLink.h
// SUMMARY: Implementation of an RTFD inclusion handler
// SUPERCLASS: eTFileLink:eTImage:Object
// INTERFACE: None
// PROTOCOLS: None added
// AUTHOR: Rohit Khare
// COPYRIGHT: (c) 1994 California Institure of Technology, eText Project
///////////////////////////////////////////////////////////////////////////////
// IMPLEMENTATION COMMENTS
// Okay: here are the facts of life about NeXT's lousy RTFD implementation
// (trust me, I know, I know the Text object every which way except from the
// inside... grrr). It goes:
// <space char>string<spacechar>\width<inTwips>\height<inTwips>\n}
// (the string spec is such that you have to read it in two passes -- that's
// why I always prefix a string by the length. (e.g. NeXT fails on a file
// named "\width960"))
//
// OK, once you have the string, you have a relative filename component. Where
// do we get the root filename component? We assume that we can reach out
// and access() [[[view etDoc] docInfo] docPath].
//
// OK, now we have a fully-qualified absolute pathname. If it's a TIFF image,
// we want to promote self to be an eTImage object encapsulating that file.
// otherwise we want to be an eTFileLink.
//
// THERE ARE NO eTRTFDFileLinks IN THE SYSTEM AFTER readRichText: !!!!
// All such instances are "promoted" by redirecting their isa pointer
// Thus, when the file is written out, RTFD-objects will be implicitly
// promoted to first-class eText objects.
//
// As an exercise for the reader: With enough cojones, it should be possible
// to write a generic mutator to eTImage-derived objects; just make sure that
// this object has as many bytes of storage as the larget morph target. Then
// you could _automatically_ morph a .snd inclusion into an eTAudio :)
///////////////////////////////////////////////////////////////////////////////
// HISTORY
// 07/23/94: Created. First actual implementation.
///////////////////////////////////////////////////////////////////////////////
#import "eTRTFDFileLink.h"
@implementation eTRTFDFileLink
+ toolAwake: theApp
{
[theApp registerAnnotation: [eTRTFDFileLink class]
name: "eTRTFDFileLink"
RTFDirective: "NeXTGraphic"
menuLabel: NULL
menuKey: '\0'
menuIcon: (NXImage *) nil];
return self;
}
- readRichText:(NXStream *) stream forView:view
{
const char *const * types;
char *ext;
NXAtom localPath,rootPath;
char buffer[MAXPATHLEN],ch;
int height=0, width=0,i=0;
char *tmp;
BOOL foundImage=NO;
// we first have to do this because this silly hack-class of ours can't
// call [super readRichText:...] (this code is in eTImage.m)
if (!etDoc || !theText) {
theText = view;
etDoc = [theText etDoc];
[etDoc registerNotification:self];
}
// first fill in the buffer with all the characters up to and including \n
while ((i < MAXPATHLEN) && ((ch = NXGetc(stream)) != '\n')) {
buffer[i++] = ch;
}
buffer[i] = 0;
// now work backward to get height.
tmp = rindex(buffer,'\\');
if (tmp && !strncmp(tmp, "\\height",7)) {
//we have a valid \height entry beginning at tmp
sscanf(tmp+7,"%d",&height);
// now nullify the \ so we can go backwards to \width
*tmp = 0;
}
// now work backward to get width.
tmp = rindex(buffer,'\\');
if (tmp && !strncmp(tmp, "\\width",6)) {
//we have a valid \height entry beginning at tmp
sscanf(tmp+6,"%d",&width);
// now nullify the \ so we can go backwards to the string
*tmp = 0;
// and also consume the space character separating string from \width
*(tmp - 1) = 0;
}
// skip the leading space -- is there one?
tmp = buffer;
if (*tmp == ' ') tmp++;
localPath = NXUniqueString(tmp);
rootPath = [[[view etDoc] docInfo] docPath];
sprintf(buffer, "%s/%s", rootPath, localPath);
// OK, now what? We have valid data.
//NXLogError("\\NeXTGraphic got \"%s\" h:%d w:%d in \"%s\"",
// localPath, height, width, rootPath);
tmp = rindex(buffer,'/'); //get the extension of the basename.
tmp = rindex(tmp,'.');
if (tmp && *(++tmp)) {
// ext is now a pointer to the extension of buffer, if there is one.
ext = NXUniqueString(tmp); // ext of basename
types = [NXImage imageFileTypes];
for(i=0; (types[i] && !foundImage); i++)
if (!strcmp(ext,types[i])) foundImage = YES;
}
if (foundImage) {
// If the target file can be viewed as imageable data, we should
// "morph" into an eTImage instance based on that file.
// The code that eTImage would execute in this situation:
// 1) create an imageComponent
// 2) [self setImageComponent]
self->isa = [eTImage class]; // assumes that we are a subclass of it
[self setImageComponent: [[[eTImageComponent alloc]
initInDoc:etDoc linked:NO]
readComponentFromPath:buffer]];
} else {
// else we need to init etFileComponent _and_ attempt to initialize
// eTImageComponent from buffer.tiff.
self->isa = [eTFileLink class];
etFileComponent = [[[eTComponent alloc] initInDoc:etDoc linked:NO]
readComponentFromPath:buffer];
strcat(buffer,".tiff"); //this is NeXT's default behavior
[self setImageComponent: [[[eTImageComponent alloc]
initInDoc:etDoc linked:NO]
readComponentFromPath:buffer]] ;
}
return self;
}
@endThese are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.